mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
.NET: Organize the .Net samples (#578)
* Organize the .Net samples * Organize the .Net samples * Merge latest from main * Update sample to also include function calling telemetry (#577) * Move package installation instructions to user-guide (#572) * Move package installation instructions to user-guide * Update user-documentation-dotnet/getting-started/README.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update docs/docs-templates/getting-started/README.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * .NET: Add SK-AF Migration Samples for Responses API. (#575) * Responses wip * Adding OpenAI Responses Migration samples * Address all samples and code for Azure and OpenAI Responses Migration code * Update dotnet/samples/SemanticKernelMigration/OpenAIResponses/Step02_ReasoningModel/Program.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Organize the .Net samples * Organize the .Net samples * Merge latest from main * Use Agent rather than AIAgent * Rename agents getting started samples * Use singular Agent --------- Co-authored-by: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
co-authored by
Copilot
Roger Barreto
parent
9b61c72e18
commit
7dee184ae4
@@ -0,0 +1,33 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<LangVersion>12</LangVersion>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.OpenAI" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
<PackageReference Include="Microsoft.Extensions.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" />
|
||||
<PackageReference Include="OpenAI" />
|
||||
<PackageReference Include="OpenTelemetry" />
|
||||
<PackageReference Include="OpenTelemetry.Exporter.Console" />
|
||||
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" />
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.Http" />
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.Runtime" />
|
||||
<PackageReference Include="OpenTelemetry.Extensions.Hosting" />
|
||||
<PackageReference Include="System.Diagnostics.DiagnosticSource" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\src\Microsoft.Extensions.AI.Agents.OpenAI\Microsoft.Extensions.AI.Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\Microsoft.Extensions.AI.Agents\Microsoft.Extensions.AI.Agents.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,216 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.Metrics;
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.AI.Agents;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using OpenTelemetry;
|
||||
using OpenTelemetry.Logs;
|
||||
using OpenTelemetry.Metrics;
|
||||
using OpenTelemetry.Resources;
|
||||
using OpenTelemetry.Trace;
|
||||
|
||||
#region Setup Telemetry
|
||||
|
||||
const string SourceName = "OpenTelemetryAspire.ConsoleApp";
|
||||
const string ServiceName = "AgentOpenTelemetry";
|
||||
|
||||
// Enable telemetry for agents
|
||||
AppContext.SetSwitch("Microsoft.Extensions.AI.Agents.EnableTelemetry", true);
|
||||
|
||||
// Configure OpenTelemetry for Aspire dashboard
|
||||
var otlpEndpoint = Environment.GetEnvironmentVariable("OTEL_EXPORTER_OTLP_ENDPOINT") ?? "http://localhost:4318";
|
||||
|
||||
// Create a resource to identify this service
|
||||
var resource = ResourceBuilder.CreateDefault()
|
||||
.AddService(ServiceName, serviceVersion: "1.0.0")
|
||||
.AddAttributes(new Dictionary<string, object>
|
||||
{
|
||||
["service.instance.id"] = Environment.MachineName,
|
||||
["deployment.environment"] = "development"
|
||||
})
|
||||
.Build();
|
||||
|
||||
// Setup tracing with resource
|
||||
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
|
||||
.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService(ServiceName, serviceVersion: "1.0.0"))
|
||||
.AddSource(SourceName) // Our custom activity source
|
||||
.AddSource("Microsoft.Extensions.AI.Agents") // Agent Framework telemetry
|
||||
.AddHttpClientInstrumentation() // Capture HTTP calls to OpenAI
|
||||
.AddOtlpExporter(options => { options.Endpoint = new Uri(otlpEndpoint); })
|
||||
.Build();
|
||||
|
||||
// Setup metrics with resource and instrument name filtering
|
||||
using var meterProvider = Sdk.CreateMeterProviderBuilder()
|
||||
.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService(ServiceName, serviceVersion: "1.0.0"))
|
||||
.AddMeter(SourceName) // Our custom meter
|
||||
.AddMeter("Microsoft.Extensions.AI.Agents") // Agent Framework metrics
|
||||
.AddHttpClientInstrumentation() // HTTP client metrics
|
||||
.AddRuntimeInstrumentation() // .NET runtime metrics
|
||||
.AddOtlpExporter(options => { options.Endpoint = new Uri(otlpEndpoint); })
|
||||
.Build();
|
||||
|
||||
// Setup structured logging with OpenTelemetry
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddLogging(loggingBuilder => loggingBuilder
|
||||
.SetMinimumLevel(LogLevel.Debug)
|
||||
.AddOpenTelemetry(options =>
|
||||
{
|
||||
options.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService(ServiceName, serviceVersion: "1.0.0"));
|
||||
options.AddOtlpExporter(otlpOptions =>
|
||||
{
|
||||
otlpOptions.Endpoint = new Uri(otlpEndpoint);
|
||||
});
|
||||
options.IncludeScopes = true;
|
||||
options.IncludeFormattedMessage = true;
|
||||
}));
|
||||
|
||||
using var activitySource = new ActivitySource(SourceName);
|
||||
using var meter = new Meter(SourceName);
|
||||
|
||||
// Create custom metrics
|
||||
var interactionCounter = meter.CreateCounter<int>("agent_interactions_total", description: "Total number of agent interactions");
|
||||
var responseTimeHistogram = meter.CreateHistogram<double>("agent_response_time_seconds", description: "Agent response time in seconds");
|
||||
|
||||
#endregion
|
||||
|
||||
var serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();
|
||||
var appLogger = loggerFactory.CreateLogger<Program>();
|
||||
|
||||
Console.WriteLine("""
|
||||
=== OpenTelemetry Aspire Demo ===
|
||||
This demo shows OpenTelemetry integration with the Agent Framework.
|
||||
You can view the telemetry data in the Aspire Dashboard.
|
||||
Type your message and press Enter. Type 'exit' or empty message to quit.
|
||||
""");
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT environment variable is not set.");
|
||||
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
// Log application startup
|
||||
appLogger.LogInformation("OpenTelemetry Aspire Demo application started");
|
||||
|
||||
[Description("Get the weather for a given location.")]
|
||||
static async Task<string> GetWeather([Description("The location to get the weather for.")] string location)
|
||||
{
|
||||
await Task.Delay(2000);
|
||||
return $"The weather in {location} is cloudy with a high of 15°C.";
|
||||
}
|
||||
|
||||
// To ensure chat client's function calling is captured in the open telemetry, the chat client needs to have UseOpenTelemetry after UseFunctionInvocation
|
||||
using var instrumentedChatClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
||||
.GetChatClient(deploymentName)
|
||||
.AsIChatClient() // Converts a native OpenAI SDK ChatClient into a Microsoft.Extensions.AI.IChatClient
|
||||
.AsBuilder()
|
||||
.UseFunctionInvocation()
|
||||
.UseOpenTelemetry(loggerFactory: loggerFactory, sourceName: SourceName, (cfg) => { cfg.EnableSensitiveData = true; })
|
||||
.Build();
|
||||
|
||||
appLogger.LogInformation("Creating Agent with OpenTelemetry instrumentation");
|
||||
// Create the agent with the instrumented chat client
|
||||
using var agent = new ChatClientAgent(instrumentedChatClient,
|
||||
name: "OpenTelemetryDemoAgent",
|
||||
instructions: "You are a helpful assistant that provides concise and informative responses.",
|
||||
tools: [AIFunctionFactory.Create(GetWeather)])
|
||||
.WithOpenTelemetry(loggerFactory, SourceName); // Enable telemetry on the agent
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
|
||||
appLogger.LogInformation("Agent created successfully with ID: {AgentId}", agent.Id);
|
||||
|
||||
// Create a parent span for the entire agent session
|
||||
using var sessionActivity = activitySource.StartActivity("Agent Session");
|
||||
var sessionId = thread.ConversationId ?? Guid.NewGuid().ToString();
|
||||
sessionActivity?.SetTag("agent.name", "OpenTelemetryDemoAgent");
|
||||
sessionActivity?.SetTag("session.id", sessionId);
|
||||
sessionActivity?.SetTag("session.start_time", DateTimeOffset.UtcNow.ToString("O"));
|
||||
|
||||
appLogger.LogInformation("Starting agent session with ID: {SessionId}", sessionId);
|
||||
using (appLogger.BeginScope(new Dictionary<string, object> { ["SessionId"] = sessionId, ["AgentName"] = "OpenTelemetryDemoAgent" }))
|
||||
{
|
||||
var interactionCount = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
Console.Write("You: ");
|
||||
var userInput = Console.ReadLine();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(userInput) || userInput.Equals("exit", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
appLogger.LogInformation("User requested to exit the session");
|
||||
break;
|
||||
}
|
||||
|
||||
interactionCount++;
|
||||
appLogger.LogInformation("Processing user interaction #{InteractionNumber}: {UserInput}", interactionCount, userInput);
|
||||
|
||||
// Create a child span for each individual interaction
|
||||
using var activity = activitySource.StartActivity("Agent Interaction");
|
||||
activity?.SetTag("user.input", userInput);
|
||||
activity?.SetTag("agent.name", "OpenTelemetryDemoAgent");
|
||||
activity?.SetTag("interaction.number", interactionCount);
|
||||
|
||||
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
|
||||
|
||||
try
|
||||
{
|
||||
appLogger.LogDebug("Starting agent execution for interaction #{InteractionNumber}", interactionCount);
|
||||
Console.Write("Agent: ");
|
||||
|
||||
// Run the agent (this will create its own internal telemetry spans)
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread))
|
||||
{
|
||||
Console.Write(update.Text);
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
|
||||
stopwatch.Stop();
|
||||
var responseTime = stopwatch.Elapsed.TotalSeconds;
|
||||
|
||||
// Record metrics (similar to Python example)
|
||||
interactionCounter.Add(1, new KeyValuePair<string, object?>("status", "success"));
|
||||
responseTimeHistogram.Record(responseTime,
|
||||
new KeyValuePair<string, object?>("status", "success"));
|
||||
|
||||
activity?.SetTag("response.success", true);
|
||||
|
||||
appLogger.LogInformation("Agent interaction #{InteractionNumber} completed successfully in {ResponseTime:F2} seconds",
|
||||
interactionCount, responseTime);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Error: {ex.Message}");
|
||||
Console.WriteLine();
|
||||
|
||||
stopwatch.Stop();
|
||||
var responseTime = stopwatch.Elapsed.TotalSeconds;
|
||||
|
||||
// Record error metrics
|
||||
interactionCounter.Add(1, new KeyValuePair<string, object?>("status", "error"));
|
||||
responseTimeHistogram.Record(responseTime,
|
||||
new KeyValuePair<string, object?>("status", "error"));
|
||||
|
||||
activity?.SetTag("response.success", false);
|
||||
activity?.SetTag("error.message", ex.Message);
|
||||
activity?.SetStatus(ActivityStatusCode.Error, ex.Message);
|
||||
|
||||
appLogger.LogError(ex, "Agent interaction #{InteractionNumber} failed after {ResponseTime:F2} seconds: {ErrorMessage}",
|
||||
interactionCount, responseTime, ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
// Add session summary to the parent span
|
||||
sessionActivity?.SetTag("session.total_interactions", interactionCount);
|
||||
sessionActivity?.SetTag("session.end_time", DateTimeOffset.UtcNow.ToString("O"));
|
||||
|
||||
appLogger.LogInformation("Agent session completed. Total interactions: {TotalInteractions}", interactionCount);
|
||||
} // End of logging scope
|
||||
|
||||
appLogger.LogInformation("OpenTelemetry Aspire Demo application shutting down");
|
||||
@@ -0,0 +1,210 @@
|
||||
# OpenTelemetry Aspire Demo with Azure OpenAI
|
||||
|
||||
This demo showcases the integration of OpenTelemetry with the Microsoft Agent Framework using Azure OpenAI and .NET Aspire Dashboard for telemetry visualization.
|
||||
|
||||
## Overview
|
||||
|
||||
The demo consists of two main components:
|
||||
|
||||
1. **Aspire Dashboard** - Provides a web-based interface to visualize OpenTelemetry data
|
||||
2. **Console Application** - An interactive console application that demonstrates agent interactions with proper OpenTelemetry instrumentation
|
||||
|
||||
## Architecture
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A["Console App<br/>(Interactive)"] --> B["Agent Framework<br/>with OpenTel<br/>Instrumentation"]
|
||||
B --> C["Azure OpenAI<br/>Service"]
|
||||
A --> D["Aspire Dashboard<br/>(OpenTelemetry Visualization)"]
|
||||
B --> D
|
||||
```
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- .NET 8.0 SDK or later
|
||||
- Azure OpenAI service endpoint and deployment configured
|
||||
- Azure CLI installed and authenticated (for Azure credential authentication)
|
||||
- Docker installed (for running Aspire Dashboard)
|
||||
|
||||
## Configuration
|
||||
|
||||
### Azure OpenAI Setup
|
||||
Set the following environment variables:
|
||||
```powershell
|
||||
$env:AZURE_OPENAI_ENDPOINT="https://your-resource.openai.azure.com/"
|
||||
$env:AZURE_OPENAI_DEPLOYMENT_NAME="gpt-4o-mini" # Optional, defaults to gpt-4o-mini
|
||||
```
|
||||
|
||||
**Note**: This demo uses Azure CLI credentials for authentication. Make sure you're logged in with `az login` and have access to the Azure OpenAI resource.
|
||||
|
||||
## Running the Demo
|
||||
|
||||
### Quick Start (Using Script)
|
||||
|
||||
The easiest way to run the demo is using the provided PowerShell script:
|
||||
|
||||
```powershell
|
||||
.\start-demo.ps1
|
||||
```
|
||||
|
||||
This script will automatically:
|
||||
- ✅ Check prerequisites (Docker, Azure OpenAI configuration)
|
||||
- 🔨 Build the console application
|
||||
- 🐳 Start the Aspire Dashboard via Docker (with anonymous access)
|
||||
- ⏳ Wait for dashboard to be ready (polls port until listening)
|
||||
- 🌐 Open your browser with the dashboard
|
||||
- 📊 Configure telemetry endpoints (http://localhost:4317)
|
||||
- 🎯 Start the interactive console application
|
||||
|
||||
### Manual Setup (Step by Step)
|
||||
|
||||
If you prefer to run the components manually:
|
||||
|
||||
#### Step 1: Start the Aspire Dashboard via Docker
|
||||
|
||||
```powershell
|
||||
docker run -d --name aspire-dashboard -p 4318:18888 -p 4317:18889 -e DOTNET_DASHBOARD_UNSECURED_ALLOW_ANONYMOUS=true mcr.microsoft.com/dotnet/aspire-dashboard:9.0
|
||||
```
|
||||
|
||||
#### Step 2: Access the Dashboard
|
||||
|
||||
Open your browser to: http://localhost:4318
|
||||
|
||||
#### Step 3: Run the Console Application
|
||||
|
||||
```powershell
|
||||
cd dotnet/demos/AgentOpenTelemetry
|
||||
$env:OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4317"
|
||||
dotnet run
|
||||
```
|
||||
|
||||
#### Interacting with the Console Application
|
||||
|
||||
You should see a welcome message like:
|
||||
|
||||
```
|
||||
=== OpenTelemetry Aspire Demo ===
|
||||
This demo shows OpenTelemetry integration with the Agent Framework.
|
||||
You can view the telemetry data in the Aspire Dashboard.
|
||||
Type your message and press Enter. Type 'exit' or empty message to quit.
|
||||
|
||||
You:
|
||||
```
|
||||
|
||||
1. Type your message and press Enter to interact with the AI agent
|
||||
2. The agent will respond, and you can continue the conversation
|
||||
3. Type `exit` to stop the application
|
||||
|
||||
**Note**: Make sure the Aspire Dashboard is running before starting the console application, as the telemetry data will be sent to the dashboard.
|
||||
|
||||
#### Step 4: Test the Integration
|
||||
|
||||
1. **Start the Aspire Dashboard** (if not already running)
|
||||
2. **Run the Console Application** in a separate terminal
|
||||
3. **Send a test message** like "Hello, how are you?"
|
||||
4. **Check the Aspire Dashboard** - you should see:
|
||||
- New traces appearing in the **Traces** tab
|
||||
- Each trace showing the complete agent interaction flow
|
||||
- Metrics in the **Metrics** tab showing token usage and duration
|
||||
- Logs in the **Structured Logs** tab with detailed information
|
||||
|
||||
## Viewing Telemetry Data
|
||||
|
||||
### Traces
|
||||
1. In the Aspire Dashboard, navigate to the **Traces** tab
|
||||
2. You'll see traces for each agent interaction
|
||||
3. Each trace contains:
|
||||
- An outer span for the entire agent interaction
|
||||
- Inner spans from the Agent Framework's OpenTelemetry instrumentation
|
||||
- Spans from HTTP calls to Azure OpenAI
|
||||
|
||||
### Metrics
|
||||
1. Navigate to the **Metrics** tab
|
||||
2. View metrics related to:
|
||||
- Agent execution duration
|
||||
- Token usage (input/output tokens)
|
||||
- Request counts
|
||||
|
||||
### Logs
|
||||
1. Navigate to the **Structured Logs** tab
|
||||
2. Filter by the console application to see detailed logs
|
||||
3. Logs include information about user inputs, agent responses, and any errors
|
||||
|
||||
## Key Features Demonstrated
|
||||
|
||||
### OpenTelemetry Integration
|
||||
- **Automatic instrumentation** of Agent Framework operations
|
||||
- **Custom spans** for user interactions
|
||||
- **Proper span lifecycle management** (create → execute → close)
|
||||
- **Telemetry correlation** across the entire request flow
|
||||
|
||||
### Agent Framework Features
|
||||
- **ChatClientAgent** with Azure OpenAI integration
|
||||
- **OpenTelemetry wrapper** using `.WithOpenTelemetry()`
|
||||
- **Conversation threading** for multi-turn conversations
|
||||
- **Error handling** with telemetry correlation
|
||||
|
||||
### Aspire Dashboard Features
|
||||
- **Real-time telemetry visualization**
|
||||
- **Distributed tracing** across services
|
||||
- **Metrics and logging** integration
|
||||
- **Resource management** and monitoring
|
||||
|
||||
## Available Script
|
||||
|
||||
The demo includes a PowerShell script to make running the demo easy:
|
||||
|
||||
### `start-demo.ps1`
|
||||
Complete demo startup script that handles everything automatically.
|
||||
|
||||
**Usage:**
|
||||
```powershell
|
||||
.\start-demo.ps1 # Start the complete demo
|
||||
```
|
||||
|
||||
**Features:**
|
||||
- **Automatic configuration detection** - Checks for Azure OpenAI configuration
|
||||
- **Project building** - Automatically builds projects before running
|
||||
- **Error handling** - Provides clear error messages if something goes wrong
|
||||
- **Multi-window support** - Opens dashboard in separate window for better experience
|
||||
- **Browser auto-launch** - Automatically opens the Aspire Dashboard in your browser
|
||||
- **Docker integration** - Uses Docker to run the Aspire Dashboard
|
||||
|
||||
**Docker Endpoints:**
|
||||
- **Aspire Dashboard**: `http://localhost:4318`
|
||||
- **OTLP Telemetry**: `http://localhost:4317`
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Port Conflicts
|
||||
If you encounter port binding errors, try:
|
||||
1. Stop any existing Docker containers using the same ports (`docker stop aspire-dashboard`)
|
||||
2. Or kill any processes using the conflicting ports
|
||||
|
||||
### Authentication Issues
|
||||
- Ensure your Azure OpenAI endpoint is correctly configured
|
||||
- Check that the environment variables are set in the correct terminal session
|
||||
- Verify you're logged in with Azure CLI (`az login`) and have access to the Azure OpenAI resource
|
||||
- Ensure the Azure OpenAI deployment name matches your actual deployment
|
||||
|
||||
### Build Issues
|
||||
- Ensure you're using .NET 9.0 SDK
|
||||
- Run `dotnet restore` if you encounter package restore issues
|
||||
- Check that all project references are correctly resolved
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
AgentOpenTelemetry/
|
||||
├── AgentOpenTelemetry.csproj # Project file with dependencies
|
||||
├── Program.cs # Main application with Azure OpenAI agent integration
|
||||
├── start-demo.ps1 # PowerShell script to start the demo
|
||||
└── README.md # This file
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
- Experiment with different prompts to see various telemetry patterns
|
||||
- Explore the Aspire Dashboard's filtering and search capabilities
|
||||
- Try modifying the OpenTelemetry configuration to add custom metrics or spans
|
||||
- Integrate additional services to see distributed tracing in action
|
||||
@@ -0,0 +1,139 @@
|
||||
# OpenTelemetry Console Demo with Aspire Dashboard (Docker)
|
||||
# This script starts the Aspire Dashboard via Docker and the Console Application
|
||||
|
||||
Write-Host "Starting OpenTelemetry Console Demo..." -ForegroundColor Green
|
||||
Write-Host ""
|
||||
|
||||
# Check if we're in the right directory
|
||||
if (!(Test-Path "AgentOpenTelemetry.csproj")) {
|
||||
Write-Host "Error: Please run this script from the AgentOpenTelemetry directory" -ForegroundColor Red
|
||||
Write-Host "Expected to find AgentOpenTelemetry.csproj file" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Check if Docker is running
|
||||
try {
|
||||
docker version | Out-Null
|
||||
Write-Host "Docker is running" -ForegroundColor Green
|
||||
} catch {
|
||||
Write-Host "Docker is not running or not installed" -ForegroundColor Red
|
||||
Write-Host "Please start Docker Desktop and try again" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Check for Azure OpenAI configuration
|
||||
if ($env:AZURE_OPENAI_ENDPOINT) {
|
||||
Write-Host "Found Azure OpenAI endpoint: $($env:AZURE_OPENAI_ENDPOINT)" -ForegroundColor Green
|
||||
if ($env:AZURE_OPENAI_DEPLOYMENT_NAME) {
|
||||
Write-Host "Using deployment: $($env:AZURE_OPENAI_DEPLOYMENT_NAME)" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "Using default deployment: gpt-4o-mini" -ForegroundColor Cyan
|
||||
}
|
||||
} else {
|
||||
Write-Host "Warning: AZURE_OPENAI_ENDPOINT not found!" -ForegroundColor Yellow
|
||||
Write-Host "Please set the AZURE_OPENAI_ENDPOINT environment variable" -ForegroundColor Yellow
|
||||
Write-Host "Example: `$env:AZURE_OPENAI_ENDPOINT='https://your-resource.openai.azure.com/'" -ForegroundColor Yellow
|
||||
Write-Host ""
|
||||
}
|
||||
|
||||
# Build console application
|
||||
Write-Host ""
|
||||
Write-Host "Building console application..." -ForegroundColor Cyan
|
||||
|
||||
$buildResult = dotnet build --verbosity quiet
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Host "Failed to build Console App" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Host "Build completed successfully" -ForegroundColor Green
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "Starting Aspire Dashboard via Docker..." -ForegroundColor Cyan
|
||||
|
||||
# Stop any existing Aspire Dashboard container
|
||||
Write-Host "Stopping any existing Aspire Dashboard container..." -ForegroundColor Gray
|
||||
docker stop aspire-dashboard-afdemo 2>$null | Out-Null
|
||||
docker rm aspire-dashboard-afdemo 2>$null | Out-Null
|
||||
|
||||
# Start Aspire Dashboard in Docker daemon mode with fixed token
|
||||
Write-Host "Starting Aspire Dashboard container..." -ForegroundColor Green
|
||||
$fixedToken = "demo-token-12345"
|
||||
$dockerResult = docker run -d `
|
||||
--name aspire-dashboard-afdemo `
|
||||
-p 4318:18888 `
|
||||
-p 4317:18889 `
|
||||
-e DOTNET_DASHBOARD_UNSECURED_ALLOW_ANONYMOUS=true `
|
||||
--restart unless-stopped `
|
||||
mcr.microsoft.com/dotnet/aspire-dashboard:9.0
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Host "Failed to start Aspire Dashboard container" -ForegroundColor Red
|
||||
Write-Host "Make sure Docker is running and try again" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Host "Aspire Dashboard started successfully!" -ForegroundColor Green
|
||||
Write-Host "OTLP Endpoint: http://localhost:4318" -ForegroundColor Cyan
|
||||
|
||||
# Wait for dashboard to be ready by polling the port
|
||||
Write-Host "Waiting for dashboard to be ready..." -ForegroundColor Gray
|
||||
$maxWaitSeconds = 10
|
||||
$waitCount = 0
|
||||
$dashboardReady = $false
|
||||
|
||||
while ($waitCount -lt $maxWaitSeconds -and !$dashboardReady) {
|
||||
try {
|
||||
$tcpConnection = Test-NetConnection -ComputerName "localhost" -Port 4317 -InformationLevel Quiet -WarningAction SilentlyContinue -ErrorAction SilentlyContinue
|
||||
if ($tcpConnection) {
|
||||
$dashboardReady = $true
|
||||
Write-Host "Dashboard is ready! (took $waitCount seconds)" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "." -NoNewline -ForegroundColor Gray
|
||||
Start-Sleep -Seconds 1
|
||||
$waitCount++
|
||||
}
|
||||
} catch {
|
||||
Write-Host "." -NoNewline -ForegroundColor Gray
|
||||
Start-Sleep -Seconds 1
|
||||
$waitCount++
|
||||
}
|
||||
}
|
||||
|
||||
if (!$dashboardReady) {
|
||||
Write-Host ""
|
||||
Write-Host "Dashboard port 4317 not responding after $maxWaitSeconds seconds" -ForegroundColor Yellow
|
||||
Write-Host " Continuing anyway - dashboard might still be starting..." -ForegroundColor Yellow
|
||||
} else {
|
||||
Write-Host ""
|
||||
}
|
||||
|
||||
# Open the dashboard in browser (anonymous access enabled)
|
||||
Write-Host "Opening dashboard in browser..." -ForegroundColor Green
|
||||
Write-Host "Dashboard URL: http://localhost:4318" -ForegroundColor Cyan
|
||||
Start-Process "http://localhost:4318"
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "Starting Console Application..." -ForegroundColor Cyan
|
||||
Write-Host "You can now interact with the AI agent!" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
|
||||
# Set the OTLP endpoint for the console application (Docker Aspire Dashboard)
|
||||
$otlpEndpoint = "http://localhost:4317"
|
||||
Write-Host "Using OTLP endpoint: $otlpEndpoint" -ForegroundColor Cyan
|
||||
|
||||
$env:OTEL_EXPORTER_OTLP_ENDPOINT = $otlpEndpoint
|
||||
|
||||
# Start the console application in the current window
|
||||
Write-Host ""
|
||||
Write-Host "Starting the console application..." -ForegroundColor Green
|
||||
Write-Host "Tip: The dashboard should now be open in your browser!" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
|
||||
dotnet run --no-build
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "Demo completed!" -ForegroundColor Green
|
||||
Write-Host "The Aspire Dashboard is still running in Docker." -ForegroundColor Gray
|
||||
Write-Host "You can view telemetry data in the browser tab that opened." -ForegroundColor Gray
|
||||
Write-Host "To stop the dashboard: docker stop aspire-dashboard-afdemo" -ForegroundColor Gray
|
||||
+4
-4
@@ -40,10 +40,10 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Microsoft.Agents.Orchestration\Microsoft.Agents.Orchestration.csproj" />
|
||||
<ProjectReference Include="..\..\src\Microsoft.Extensions.AI.Agents.AzureAI\Microsoft.Extensions.AI.Agents.AzureAI.csproj" />
|
||||
<ProjectReference Include="..\..\src\Microsoft.Extensions.AI.Agents.OpenAI\Microsoft.Extensions.AI.Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\src\Microsoft.Extensions.AI.Agents\Microsoft.Extensions.AI.Agents.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\Microsoft.Agents.Orchestration\Microsoft.Agents.Orchestration.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\Microsoft.Extensions.AI.Agents.AzureAI\Microsoft.Extensions.AI.Agents.AzureAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\Microsoft.Extensions.AI.Agents.OpenAI\Microsoft.Extensions.AI.Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\Microsoft.Extensions.AI.Agents\Microsoft.Extensions.AI.Agents.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -0,0 +1,22 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<LangVersion>12</LangVersion>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="A2A" />
|
||||
<PackageReference Include="System.Net.ServerSentEvents" VersionOverride="10.0.0-preview.5.25277.114" />
|
||||
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" VersionOverride="10.0.0-preview.5.25277.114" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Extensions.AI.Agents.A2A\Microsoft.Extensions.AI.Agents.A2A.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,20 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to create and use a simple AI agent with an existing A2A agent.
|
||||
|
||||
using System;
|
||||
using A2A;
|
||||
using Microsoft.Extensions.AI.Agents;
|
||||
using Microsoft.Extensions.AI.Agents.A2A;
|
||||
|
||||
var a2aAgentHost = Environment.GetEnvironmentVariable("A2A_AGENT_HOST") ?? throw new InvalidOperationException("A2A_AGENT_HOST is not set.");
|
||||
|
||||
// Initialize an A2ACardResolver to get an A2A agent card.
|
||||
A2ACardResolver agentCardResolver = new(new Uri(a2aAgentHost));
|
||||
|
||||
// Create an instance of the AIAgent for an existing A2A agent specified by the agent card.
|
||||
AIAgent agent = await agentCardResolver.GetAIAgentAsync();
|
||||
|
||||
// Invoke the agent and output the text result.
|
||||
AgentRunResponse response = await agent.RunAsync("Tell me a joke about a pirate.");
|
||||
Console.WriteLine(response);
|
||||
@@ -0,0 +1,34 @@
|
||||
# Prerequisites
|
||||
|
||||
Before you begin, ensure you have the following prerequisites:
|
||||
|
||||
- .NET 8.0 SDK or later
|
||||
- Access to the A2A agent host service
|
||||
|
||||
**Note**: These samples need to be run against a valid A2A server. If no A2A server is available, they can be run against the echo-agent that can be spun up locally by following the guidelines at: https://github.com/a2aproject/a2a-dotnet/blob/main/samples/AgentServer/README.md
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
$env:A2A_AGENT_HOST="https://your-a2a-agent-host" # Replace with your A2A agent host endpoint
|
||||
```
|
||||
|
||||
## Advanced scenario
|
||||
|
||||
This method can be used to create AI agents for A2A agents whose hosts support the [Direct Configuration / Private Discovery](https://github.com/a2aproject/A2A/blob/main/docs/topics/agent-discovery.md#3-direct-configuration--private-discovery) discovery mechanism.
|
||||
|
||||
```csharp
|
||||
using A2A;
|
||||
using Microsoft.Extensions.AI.Agents;
|
||||
using Microsoft.Extensions.AI.Agents.A2A;
|
||||
|
||||
// Create an A2AClient pointing to your `echo` A2A agent endpoint
|
||||
A2AClient a2aClient = new(new Uri("https://your-a2a-agent-host/echo"));
|
||||
|
||||
// Create an AIAgent from the A2AClient
|
||||
AIAgent agent = a2aClient.GetAIAgent();
|
||||
|
||||
// Run the agent
|
||||
AgentRunResponse response = await agent.RunAsync("Tell me a joke about a pirate.");
|
||||
Console.WriteLine(response);
|
||||
```
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<LangVersion>12</LangVersion>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.Agents.Persistent" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Extensions.AI.Agents.AzureAI\Microsoft.Extensions.AI.Agents.AzureAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Extensions.AI.Agents\Microsoft.Extensions.AI.Agents.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,41 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to create and use a simple AI agent with Azure Foundry Agents as the backend.
|
||||
|
||||
using System;
|
||||
using Azure.AI.Agents.Persistent;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Extensions.AI.Agents;
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set.");
|
||||
var deploymentName = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
const string JokerName = "Joker";
|
||||
const string JokerInstructions = "You are good at telling jokes.";
|
||||
|
||||
// Get a client to create/retrieve server side agents with.
|
||||
var persistentAgentsClient = new PersistentAgentsClient(endpoint, new AzureCliCredential());
|
||||
|
||||
// You can create a server side persistent agent with the Azure.AI.Agents.Persistent SDK.
|
||||
var agentMetadata = await persistentAgentsClient.Administration.CreateAgentAsync(
|
||||
model: deploymentName,
|
||||
name: JokerName,
|
||||
instructions: JokerInstructions);
|
||||
|
||||
// You can retrieve an already created server side persistent agent as an AIAgent.
|
||||
AIAgent agent1 = await persistentAgentsClient.GetAIAgentAsync(agentMetadata.Value.Id);
|
||||
|
||||
// You can also create a server side persistent agent and return it as an AIAgent directly.
|
||||
AIAgent agent2 = await persistentAgentsClient.CreateAIAgentAsync(
|
||||
model: deploymentName,
|
||||
name: JokerName,
|
||||
instructions: JokerInstructions);
|
||||
|
||||
// You can then invoke the agent like any other AIAgent.
|
||||
AgentThread thread = agent1.GetNewThread();
|
||||
Console.WriteLine(await agent1.RunAsync("Tell me a joke about a pirate.", thread));
|
||||
|
||||
// Cleanup for sample purposes.
|
||||
await persistentAgentsClient.Threads.DeleteThreadAsync(thread.ConversationId);
|
||||
await persistentAgentsClient.Administration.DeleteAgentAsync(agent1.Id);
|
||||
await persistentAgentsClient.Administration.DeleteAgentAsync(agent2.Id);
|
||||
@@ -0,0 +1,16 @@
|
||||
# Prerequisites
|
||||
|
||||
Before you begin, ensure you have the following prerequisites:
|
||||
|
||||
- .NET 8.0 SDK or later
|
||||
- Azure Foundry service endpoint and deployment configured
|
||||
- Azure CLI installed and authenticated (for Azure credential authentication)
|
||||
|
||||
**Note**: This demo uses Azure CLI credentials for authentication. Make sure you're logged in with `az login` and have access to the Azure Foundry resource. For more information, see the [Azure CLI documentation](https://learn.microsoft.com/cli/azure/authenticate-azure-cli-interactively).
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
$env:AZURE_FOUNDRY_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.com/api/projects/your-foundry-project" # Replace with your Azure Foundry resource endpoint
|
||||
$env:AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME="gpt-4o-mini" # Optional, defaults to gpt-4o-mini
|
||||
```
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<LangVersion>12</LangVersion>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.OpenAI" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
<PackageReference Include="Microsoft.Extensions.AI.OpenAI" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Extensions.AI.Agents.OpenAI\Microsoft.Extensions.AI.Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Extensions.AI.Agents\Microsoft.Extensions.AI.Agents.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to create and use a simple AI agent with Azure OpenAI Chat Completion as the backend.
|
||||
|
||||
using System;
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Extensions.AI.Agents;
|
||||
using OpenAI;
|
||||
|
||||
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";
|
||||
|
||||
const string JokerName = "Joker";
|
||||
const string JokerInstructions = "You are good at telling jokes.";
|
||||
|
||||
AIAgent agent = new AzureOpenAIClient(
|
||||
new Uri(endpoint),
|
||||
new AzureCliCredential())
|
||||
.GetChatClient(deploymentName)
|
||||
.CreateAIAgent(JokerInstructions, JokerName);
|
||||
|
||||
// Invoke the agent and output the text result.
|
||||
Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate."));
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
# Prerequisites
|
||||
|
||||
Before you begin, ensure you have the following prerequisites:
|
||||
|
||||
- .NET 8.0 SDK or later
|
||||
- Azure OpenAI service endpoint and deployment configured
|
||||
- Azure CLI installed and authenticated (for Azure credential authentication)
|
||||
|
||||
**Note**: This demo uses Azure CLI credentials for authentication. Make sure you're logged in with `az login` and have access to the Azure OpenAI resource. For more information, see the [Azure CLI documentation](https://learn.microsoft.com/cli/azure/authenticate-azure-cli-interactively).
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
$env:AZURE_OPENAI_ENDPOINT="https://your-resource.openai.azure.com/" # Replace with your Azure OpenAI resource endpoint
|
||||
$env:AZURE_OPENAI_DEPLOYMENT_NAME="gpt-4o-mini" # Optional, defaults to gpt-4o-mini
|
||||
```
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<LangVersion>12</LangVersion>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.OpenAI" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
<PackageReference Include="Microsoft.Extensions.AI.OpenAI" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Extensions.AI.Agents.OpenAI\Microsoft.Extensions.AI.Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Extensions.AI.Agents\Microsoft.Extensions.AI.Agents.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to create and use a simple AI agent with Azure OpenAI Responses as the backend.
|
||||
|
||||
#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.
|
||||
|
||||
using System;
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Extensions.AI.Agents;
|
||||
using OpenAI;
|
||||
|
||||
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";
|
||||
|
||||
const string JokerName = "Joker";
|
||||
const string JokerInstructions = "You are good at telling jokes.";
|
||||
|
||||
AIAgent agent = new AzureOpenAIClient(
|
||||
new Uri(endpoint),
|
||||
new AzureCliCredential())
|
||||
.GetOpenAIResponseClient(deploymentName)
|
||||
.CreateAIAgent(JokerInstructions, JokerName);
|
||||
|
||||
// Invoke the agent and output the text result.
|
||||
Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate."));
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
# Prerequisites
|
||||
|
||||
Before you begin, ensure you have the following prerequisites:
|
||||
|
||||
- .NET 8.0 SDK or later
|
||||
- Azure OpenAI service endpoint and deployment configured
|
||||
- Azure CLI installed and authenticated (for Azure credential authentication)
|
||||
|
||||
**Note**: This demo uses Azure CLI credentials for authentication. Make sure you're logged in with `az login` and have access to the Azure OpenAI resource. For more information, see the [Azure CLI documentation](https://learn.microsoft.com/cli/azure/authenticate-azure-cli-interactively).
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
$env:AZURE_OPENAI_ENDPOINT="https://your-resource.openai.azure.com/" # Replace with your Azure OpenAI resource endpoint
|
||||
$env:AZURE_OPENAI_DEPLOYMENT_NAME="gpt-4o-mini" # Optional, defaults to gpt-4o-mini
|
||||
```
|
||||
@@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<LangVersion>12</LangVersion>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.ML.OnnxRuntimeGenAI" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Extensions.AI.Agents\Microsoft.Extensions.AI.Agents.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,20 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to create and use a simple AI agent with ONNX as the backend.
|
||||
|
||||
using System;
|
||||
using Microsoft.Extensions.AI.Agents;
|
||||
using Microsoft.ML.OnnxRuntimeGenAI;
|
||||
|
||||
// E.g. C:\repos\Phi-4-mini-instruct-onnx\cpu_and_mobile\cpu-int4-rtn-block-32-acc-level-4
|
||||
var modelPath = Environment.GetEnvironmentVariable("ONNX_MODEL_PATH") ?? throw new InvalidOperationException("ONNX_MODEL_PATH is not set.");
|
||||
|
||||
const string JokerName = "Joker";
|
||||
const string JokerInstructions = "You are good at telling jokes.";
|
||||
|
||||
// Get a chat client for ONNX and use it to construct an AIAgent.
|
||||
using OnnxRuntimeGenAIChatClient chatClient = new(modelPath);
|
||||
AIAgent agent = new ChatClientAgent(chatClient, JokerInstructions, JokerName);
|
||||
|
||||
// Invoke the agent and output the text result.
|
||||
Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate."));
|
||||
@@ -0,0 +1,12 @@
|
||||
# Prerequisites
|
||||
|
||||
Before you begin, ensure you have the following prerequisites:
|
||||
|
||||
- .NET 8.0 SDK or later
|
||||
- An ONNX model downloaded to your machine
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
$env:ONNX_MODEL_PATH="C:\repos\Phi-4-mini-instruct-onnx\cpu_and_mobile\cpu-int4-rtn-block-32-acc-level-4" # Replace with your model path
|
||||
```
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<LangVersion>12</LangVersion>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Extensions.AI.Agents.OpenAI\Microsoft.Extensions.AI.Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Extensions.AI.Agents\Microsoft.Extensions.AI.Agents.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to create and use a simple AI agent with OpenAI Chat Completion as the backend.
|
||||
|
||||
using System;
|
||||
using Microsoft.Extensions.AI.Agents;
|
||||
using OpenAI;
|
||||
|
||||
var apiKey = Environment.GetEnvironmentVariable("OPENAI_APIKEY") ?? throw new InvalidOperationException("OPENAI_APIKEY is not set.");
|
||||
var modelName = Environment.GetEnvironmentVariable("OPENAI_MODEL") ?? "gpt-4o-mini";
|
||||
|
||||
const string JokerName = "Joker";
|
||||
const string JokerInstructions = "You are good at telling jokes.";
|
||||
|
||||
AIAgent agent = new OpenAIClient(
|
||||
apiKey)
|
||||
.GetChatClient(modelName)
|
||||
.CreateAIAgent(JokerInstructions, JokerName);
|
||||
|
||||
// Invoke the agent and output the text result.
|
||||
Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate."));
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
# Prerequisites
|
||||
|
||||
Before you begin, ensure you have the following prerequisites:
|
||||
|
||||
- .NET 8.0 SDK or later
|
||||
- OpenAI api key
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
$env:OPENAI_APIKEY="*****" # Replace with your OpenAI api key
|
||||
$env:OPENAI_MODEL="gpt-4o-mini" # Optional, defaults to gpt-4o-mini
|
||||
```
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<LangVersion>12</LangVersion>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Extensions.AI.Agents.OpenAI\Microsoft.Extensions.AI.Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Extensions.AI.Agents\Microsoft.Extensions.AI.Agents.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to create and use a simple AI agent with OpenAI Responses as the backend.
|
||||
|
||||
#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.
|
||||
|
||||
using System;
|
||||
using Microsoft.Extensions.AI.Agents;
|
||||
using OpenAI;
|
||||
|
||||
var apiKey = Environment.GetEnvironmentVariable("OPENAI_APIKEY") ?? throw new InvalidOperationException("OPENAI_APIKEY is not set.");
|
||||
var modelName = Environment.GetEnvironmentVariable("OPENAI_MODEL") ?? "gpt-4o-mini";
|
||||
|
||||
const string JokerName = "Joker";
|
||||
const string JokerInstructions = "You are good at telling jokes.";
|
||||
|
||||
AIAgent agent = new OpenAIClient(
|
||||
apiKey)
|
||||
.GetOpenAIResponseClient(modelName)
|
||||
.CreateAIAgent(JokerInstructions, JokerName);
|
||||
|
||||
// Invoke the agent and output the text result.
|
||||
Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate."));
|
||||
@@ -0,0 +1,13 @@
|
||||
# Prerequisites
|
||||
|
||||
Before you begin, ensure you have the following prerequisites:
|
||||
|
||||
- .NET 8.0 SDK or later
|
||||
- OpenAI api key
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
$env:OPENAI_APIKEY="*****" # Replace with your OpenAI api key
|
||||
$env:OPENAI_MODEL="gpt-4o-mini" # Optional, defaults to gpt-4o-mini
|
||||
```
|
||||
@@ -0,0 +1,56 @@
|
||||
# Creating an AIAgent instance for various providers
|
||||
|
||||
These samples show how to create an AIAgent instance using various providers.
|
||||
This is not an exhaustive list, but shows a variety of the more popular options.
|
||||
|
||||
For other samples that demonstrate how to use AIAgent instances,
|
||||
see the [Getting Started Steps](../GettingStartedSteps/README.md) samples.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
See the README.md for each sample for the prerequisites for that sample.
|
||||
## Samples
|
||||
|
||||
|Sample|Description|
|
||||
|---|---|
|
||||
|[Creating an AIAgent with A2A](./AIAgent_With_A2A/)|This sample demonstrates how to create AIAgent for an existing A2A agent.|
|
||||
|[Creating an AIAgent with AzureFoundry](./AIAgent_With_AzureFoundry/)|This sample demonstrates how to create an Azure Foundry agent and expose it as an AIAgent|
|
||||
|[Creating an AIAgent with Azure OpenAI ChatCompletion](./AIAgent_With_AzureOpenAIChatCompletion/)|This sample demonstrates how to create an AIAgent using Azure OpenAI ChatCompletion as the underlying inference service|
|
||||
|[Creating an AIAgent with Azure OpenAI Responses](./AIAgent_With_AzureOpenAIResponses/)|This sample demonstrates how to create an AIAgent using Azure OpenAI Responses as the underlying inference service|
|
||||
|[Creating an AIAgent with ONNX](./AIAgent_With_ONNX/)|This sample demonstrates how to create an AIAgent using ONNX as the underlying inference service|
|
||||
|[Creating an AIAgent with OpenAI ChatCompletion](./AIAgent_With_OpenAIChatCompletion/)|This sample demonstrates how to create an AIAgent using OpenAI ChatCompletion as the underlying inference service|
|
||||
|[Creating an AIAgent with OpenAI Responses](./AIAgent_With_OpenAIResponses/)|This sample demonstrates how to create an AIAgent using OpenAI Responses as the underlying inference service|
|
||||
|
||||
## Running the samples from the console
|
||||
|
||||
To run the samples, navigate to the desired sample directory, e.g.
|
||||
|
||||
```powershell
|
||||
cd AIAgent_With_AzureOpenAIChatCompletion
|
||||
```
|
||||
|
||||
Set the required environment variables as documented in the sample readme.
|
||||
If the variables are not set, you will be prompted for the values when running the samples.
|
||||
Execute the following command to build the sample:
|
||||
|
||||
```powershell
|
||||
dotnet build
|
||||
```
|
||||
|
||||
Execute the following command to run the sample:
|
||||
|
||||
```powershell
|
||||
dotnet run --no-build
|
||||
```
|
||||
|
||||
Or just build and run in one step:
|
||||
|
||||
```powershell
|
||||
dotnet run
|
||||
```
|
||||
|
||||
## Running the samples from Visual Studio
|
||||
|
||||
Open the solution in Visual Studio and set the desired sample project as the startup project. Then, run the project using the built-in debugger or by pressing `F5`.
|
||||
|
||||
You will be prompted for any required environment variables if they are not already set.
|
||||
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<LangVersion>12</LangVersion>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.OpenAI" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
<PackageReference Include="Microsoft.Extensions.AI.OpenAI" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Extensions.AI.Agents.OpenAI\Microsoft.Extensions.AI.Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Extensions.AI.Agents\Microsoft.Extensions.AI.Agents.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,30 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to create and use a simple AI agent with Azure OpenAI as the backend.
|
||||
|
||||
using System;
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Extensions.AI.Agents;
|
||||
using OpenAI;
|
||||
|
||||
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";
|
||||
|
||||
const string JokerName = "Joker";
|
||||
const string JokerInstructions = "You are good at telling jokes.";
|
||||
|
||||
AIAgent agent = new AzureOpenAIClient(
|
||||
new Uri(endpoint),
|
||||
new AzureCliCredential())
|
||||
.GetChatClient(deploymentName)
|
||||
.CreateAIAgent(JokerInstructions, JokerName);
|
||||
|
||||
// Invoke the agent and output the text result.
|
||||
Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate."));
|
||||
|
||||
// Invoke the agent with streaming support.
|
||||
await foreach (var update in agent.RunStreamingAsync("Tell me a joke about a pirate."))
|
||||
{
|
||||
Console.WriteLine(update);
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<LangVersion>12</LangVersion>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.OpenAI" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
<PackageReference Include="Microsoft.Extensions.AI.OpenAI" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Extensions.AI.Agents.OpenAI\Microsoft.Extensions.AI.Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Extensions.AI.Agents\Microsoft.Extensions.AI.Agents.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,37 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to create and use a simple AI agent with a multi-turn conversation.
|
||||
|
||||
using System;
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Extensions.AI.Agents;
|
||||
using OpenAI;
|
||||
|
||||
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";
|
||||
|
||||
const string JokerName = "Joker";
|
||||
const string JokerInstructions = "You are good at telling jokes.";
|
||||
|
||||
AIAgent agent = new AzureOpenAIClient(
|
||||
new Uri(endpoint),
|
||||
new AzureCliCredential())
|
||||
.GetChatClient(deploymentName)
|
||||
.CreateAIAgent(JokerInstructions, JokerName);
|
||||
|
||||
// Invoke the agent with a multi-turn conversation, where the context is preserved in the thread object.
|
||||
AgentThread thread = agent.GetNewThread();
|
||||
Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate.", thread));
|
||||
Console.WriteLine(await agent.RunAsync("Now add some emojis to the joke and tell it in the voice of a pirate's parrot.", thread));
|
||||
|
||||
// Invoke the agent with a multi-turn conversation and streaming, where the context is preserved in the thread object.
|
||||
thread = agent.GetNewThread();
|
||||
await foreach (var update in agent.RunStreamingAsync("Tell me a joke about a pirate.", thread))
|
||||
{
|
||||
Console.WriteLine(update);
|
||||
}
|
||||
await foreach (var update in agent.RunStreamingAsync("Now add some emojis to the joke and tell it in the voice of a pirate's parrot.", thread))
|
||||
{
|
||||
Console.WriteLine(update);
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<LangVersion>12</LangVersion>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.OpenAI" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
<PackageReference Include="Microsoft.Extensions.AI.OpenAI" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Extensions.AI.Agents.OpenAI\Microsoft.Extensions.AI.Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Extensions.AI.Agents\Microsoft.Extensions.AI.Agents.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,35 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample demonstrates how to use a ChatClientAgent with function tools.
|
||||
// It shows both non-streaming and streaming agent interactions using menu-related tools.
|
||||
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.AI.Agents;
|
||||
using OpenAI;
|
||||
|
||||
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";
|
||||
|
||||
[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.";
|
||||
|
||||
// Create the chat client and agent, and provide the function tool to the agent.
|
||||
AIAgent agent = new AzureOpenAIClient(
|
||||
new Uri(endpoint),
|
||||
new AzureCliCredential())
|
||||
.GetChatClient(deploymentName)
|
||||
.CreateAIAgent(instructions: "You are a helpful assistant", tools: [AIFunctionFactory.Create(GetWeather)]);
|
||||
|
||||
// Non-streaming agent interaction with function tools.
|
||||
Console.WriteLine(await agent.RunAsync("What is the weather like in Amsterdam?"));
|
||||
|
||||
// Streaming agent interaction with function tools.
|
||||
await foreach (var update in agent.RunStreamingAsync("What is the weather like in Amsterdam?"))
|
||||
{
|
||||
Console.WriteLine(update);
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<LangVersion>12</LangVersion>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.OpenAI" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
<PackageReference Include="Microsoft.Extensions.AI.OpenAI" />
|
||||
<PackageReference Include="System.Linq.Async" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Extensions.AI.Agents.OpenAI\Microsoft.Extensions.AI.Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Extensions.AI.Agents\Microsoft.Extensions.AI.Agents.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample demonstrates how to use a ChatClientAgent with function tools that require a human in the loop for approvals.
|
||||
// It shows both non-streaming and streaming agent interactions using menu-related tools.
|
||||
// If the agent is hosted in a service, with a remote user, combine this sample with the Persisted Conversations sample to persist the chat history
|
||||
// while the agent is waiting for user input.
|
||||
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.AI.Agents;
|
||||
using OpenAI;
|
||||
|
||||
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";
|
||||
|
||||
// Create a sample function tool that the agent can use.
|
||||
[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.";
|
||||
|
||||
// Create the chat client and agent.
|
||||
// Note that we are wrapping the function tool with ApprovalRequiredAIFunction to require user approval before invoking it.
|
||||
AIAgent agent = new AzureOpenAIClient(
|
||||
new Uri(endpoint),
|
||||
new AzureCliCredential())
|
||||
.GetChatClient(deploymentName)
|
||||
.CreateAIAgent(instructions: "You are a helpful assistant", tools: [new ApprovalRequiredAIFunction(AIFunctionFactory.Create(GetWeather))]);
|
||||
|
||||
// Call the agent and check if there are any user input requests to handle.
|
||||
AgentThread thread = agent.GetNewThread();
|
||||
var response = await agent.RunAsync("What is the weather like in Amsterdam?", thread);
|
||||
var userInputRequests = response.UserInputRequests.ToList();
|
||||
|
||||
// For streaming use:
|
||||
// var updates = await agent.RunStreamingAsync("What is the weather like in Amsterdam?", thread).ToListAsync();
|
||||
// userInputRequests = updates.SelectMany(x => x.UserInputRequests).ToList();
|
||||
|
||||
while (userInputRequests.Count > 0)
|
||||
{
|
||||
// Ask the user to approve each function call request.
|
||||
// For simplicity, we are assuming here that only function approval requests are being made.
|
||||
var userInputResponses = userInputRequests
|
||||
.OfType<FunctionApprovalRequestContent>()
|
||||
.Select(functionApprovalRequest =>
|
||||
{
|
||||
Console.WriteLine($"The agent would like to invoke the following function, please reply Y to approve: Name {functionApprovalRequest.FunctionCall.Name}");
|
||||
return new ChatMessage(ChatRole.User, [functionApprovalRequest.CreateResponse(Console.ReadLine()?.Equals("Y", StringComparison.OrdinalIgnoreCase) ?? false)]);
|
||||
})
|
||||
.ToList();
|
||||
|
||||
// Pass the user input responses back to the agent for further processing.
|
||||
response = await agent.RunAsync(userInputResponses, thread);
|
||||
|
||||
userInputRequests = response.UserInputRequests.ToList();
|
||||
|
||||
// For streaming use:
|
||||
// updates = await agent.RunStreamingAsync(userInputResponses, thread).ToListAsync();
|
||||
// userInputRequests = updates.SelectMany(x => x.UserInputRequests).ToList();
|
||||
}
|
||||
|
||||
Console.WriteLine($"\nAgent: {response}");
|
||||
|
||||
// For streaming use:
|
||||
// Console.WriteLine($"\nAgent: {updates.ToAgentRunResponse()}");
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<LangVersion>12</LangVersion>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.OpenAI" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
<PackageReference Include="Microsoft.Extensions.AI.OpenAI" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Extensions.AI.Agents.OpenAI\Microsoft.Extensions.AI.Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Extensions.AI.Agents\Microsoft.Extensions.AI.Agents.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,76 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to create and use a simple AI agent with Azure OpenAI as the backend, to produce structured output using JSON schema from a class.
|
||||
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.AI.Agents;
|
||||
using OpenAI;
|
||||
using SampleApp;
|
||||
|
||||
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";
|
||||
|
||||
// Create the agent options, specifying the response format to use a JSON schema based on the PersonInfo class.
|
||||
ChatClientAgentOptions agentOptions = new(name: "HelpfulAssistant", instructions: "You are a helpful assistant.")
|
||||
{
|
||||
ChatOptions = new()
|
||||
{
|
||||
ResponseFormat = ChatResponseFormatJson.ForJsonSchema(
|
||||
schema: AIJsonUtilities.CreateJsonSchema(typeof(PersonInfo)),
|
||||
schemaName: "PersonInfo",
|
||||
schemaDescription: "Information about a person including their name, age, and occupation")
|
||||
}
|
||||
};
|
||||
|
||||
// Create the agent using Azure OpenAI.
|
||||
AIAgent agent = new AzureOpenAIClient(
|
||||
new Uri(endpoint),
|
||||
new AzureCliCredential())
|
||||
.GetChatClient(deploymentName)
|
||||
.CreateAIAgent(agentOptions);
|
||||
|
||||
// Invoke the agent with some unstructured input, to extract the structured information from.
|
||||
var response = await agent.RunAsync("Please provide information about John Smith, who is a 35-year-old software engineer.");
|
||||
|
||||
// Deserialize the response into the PersonInfo class.
|
||||
var personInfo = response.Deserialize<PersonInfo>(JsonSerializerOptions.Web);
|
||||
|
||||
Console.WriteLine("Assistant Output:");
|
||||
Console.WriteLine($"Name: {personInfo.Name}");
|
||||
Console.WriteLine($"Age: {personInfo.Age}");
|
||||
Console.WriteLine($"Occupation: {personInfo.Occupation}");
|
||||
|
||||
// Invoke the agent with some unstructured input while streaming, to extract the structured information from.
|
||||
var updates = agent.RunStreamingAsync("Please provide information about John Smith, who is a 35-year-old software engineer.");
|
||||
|
||||
// Assemble all the parts of the streamed output, since we can only deserialize once we have the full json,
|
||||
// then deserialize the response into the PersonInfo class.
|
||||
personInfo = (await updates.ToAgentRunResponseAsync()).Deserialize<PersonInfo>(JsonSerializerOptions.Web);
|
||||
|
||||
Console.WriteLine("Assistant Output:");
|
||||
Console.WriteLine($"Name: {personInfo.Name}");
|
||||
Console.WriteLine($"Age: {personInfo.Age}");
|
||||
Console.WriteLine($"Occupation: {personInfo.Occupation}");
|
||||
|
||||
namespace SampleApp
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents information about a person, including their name, age, and occupation, matched to the JSON schema used in the agent.
|
||||
/// </summary>
|
||||
public class PersonInfo
|
||||
{
|
||||
[JsonPropertyName("name")]
|
||||
public string? Name { get; set; }
|
||||
|
||||
[JsonPropertyName("age")]
|
||||
public int? Age { get; set; }
|
||||
|
||||
[JsonPropertyName("occupation")]
|
||||
public string? Occupation { get; set; }
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<LangVersion>12</LangVersion>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.OpenAI" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
<PackageReference Include="Microsoft.Extensions.AI.OpenAI" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Extensions.AI.Agents.OpenAI\Microsoft.Extensions.AI.Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Extensions.AI.Agents\Microsoft.Extensions.AI.Agents.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,46 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to create and use a simple AI agent with a conversation that can be persisted to disk.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Extensions.AI.Agents;
|
||||
using OpenAI;
|
||||
|
||||
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";
|
||||
|
||||
const string JokerName = "Joker";
|
||||
const string JokerInstructions = "You are good at telling jokes.";
|
||||
|
||||
// Create the agent
|
||||
AIAgent agent = new AzureOpenAIClient(
|
||||
new Uri(endpoint),
|
||||
new AzureCliCredential())
|
||||
.GetChatClient(deploymentName)
|
||||
.CreateAIAgent(JokerInstructions, JokerName);
|
||||
|
||||
// Start a new thread for the agent conversation.
|
||||
AgentThread thread = agent.GetNewThread();
|
||||
|
||||
// Run the agent with a new thread.
|
||||
Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate.", thread));
|
||||
|
||||
// Serialize the thread state to a JsonElement, so it can be stored for later use.
|
||||
JsonElement serializedThread = await thread.SerializeAsync();
|
||||
|
||||
// Save the serialized thread to a temporary file (for demonstration purposes).
|
||||
string tempFilePath = Path.GetTempFileName();
|
||||
await File.WriteAllTextAsync(tempFilePath, JsonSerializer.Serialize(serializedThread));
|
||||
|
||||
// Load the serialized thread from the temporary file (for demonstration purposes).
|
||||
JsonElement reloadedSerializedThread = JsonSerializer.Deserialize<JsonElement>(await File.ReadAllTextAsync(tempFilePath));
|
||||
|
||||
// Deserialize the thread state after loading from storage.
|
||||
AgentThread resumedThread = await agent.DeserializeThreadAsync(reloadedSerializedThread);
|
||||
|
||||
// Run the agent again with the resumed thread.
|
||||
Console.WriteLine(await agent.RunAsync("Now tell the same joke in the voice of a pirate, and add some emojis to the joke.", resumedThread));
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<LangVersion>12</LangVersion>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.OpenAI" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
<PackageReference Include="Microsoft.Extensions.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel.Connectors.InMemory" />
|
||||
<PackageReference Include="System.Linq.Async" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Extensions.AI.Agents.OpenAI\Microsoft.Extensions.AI.Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Extensions.AI.Agents\Microsoft.Extensions.AI.Agents.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,155 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
#pragma warning disable CA1869 // Cache and reuse 'JsonSerializerOptions' instances
|
||||
|
||||
// This sample shows how to create and use a simple AI agent with a conversation that can be persisted to disk.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.AI.Agents;
|
||||
using Microsoft.Extensions.VectorData;
|
||||
using Microsoft.SemanticKernel.Connectors.InMemory;
|
||||
using OpenAI;
|
||||
using SampleApp;
|
||||
|
||||
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";
|
||||
|
||||
const string JokerName = "Joker";
|
||||
const string JokerInstructions = "You are good at telling jokes.";
|
||||
|
||||
// Create a vector store to store the chat messages in.
|
||||
// Replace this with a vector store implementation of your choice if you want to persist the chat history to disk.
|
||||
VectorStore vectorStore = new InMemoryVectorStore();
|
||||
|
||||
// Create the agent
|
||||
AIAgent agent = new AzureOpenAIClient(
|
||||
new Uri(endpoint),
|
||||
new AzureCliCredential())
|
||||
.GetChatClient(deploymentName)
|
||||
.CreateAIAgent(new ChatClientAgentOptions
|
||||
{
|
||||
Name = JokerName,
|
||||
Instructions = JokerInstructions,
|
||||
ChatMessageStoreFactory = () =>
|
||||
{
|
||||
// Create a new chat message store for this agent that stores the messages in a vector store.
|
||||
// Each thread must get its own copy of the VectorChatMessageStore, since the store
|
||||
// also contains the id that the thread is stored under.
|
||||
return new VectorChatMessageStore(vectorStore);
|
||||
}
|
||||
});
|
||||
|
||||
// Start a new thread for the agent conversation.
|
||||
AgentThread thread = agent.GetNewThread();
|
||||
|
||||
// Run the agent with the thread that stores conversation history in the vector store.
|
||||
Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate.", thread));
|
||||
|
||||
// Serialize the thread state, so it can be stored for later use.
|
||||
// Since the chat history is stored in the vector store, the serialized thread
|
||||
// only contains the guid that the messages are stored under in the vector store.
|
||||
JsonElement serializedThread = await thread.SerializeAsync();
|
||||
|
||||
Console.WriteLine("\n--- Serialized thread ---\n");
|
||||
Console.WriteLine(JsonSerializer.Serialize(serializedThread, new JsonSerializerOptions { WriteIndented = true }));
|
||||
|
||||
// The serialized thread can now be saved to a database, file, or any other storage mechanism
|
||||
// and loaded again later.
|
||||
|
||||
// Deserialize the thread state after loading from storage.
|
||||
AgentThread resumedThread = await agent.DeserializeThreadAsync(serializedThread);
|
||||
|
||||
// Run the agent with the thread that stores conversation history in the vector store a second time.
|
||||
Console.WriteLine(await agent.RunAsync("Now tell the same joke in the voice of a pirate, and add some emojis to the joke.", resumedThread));
|
||||
|
||||
namespace SampleApp
|
||||
{
|
||||
/// <summary>
|
||||
/// A sample implementation of <see cref="IChatMessageStore"/> that stores chat messages in a vector store.
|
||||
/// </summary>
|
||||
/// <param name="vectorStore">The vector store to store the messages in.</param>
|
||||
internal sealed class VectorChatMessageStore(VectorStore vectorStore) : IChatMessageStore
|
||||
{
|
||||
private string? _threadId;
|
||||
|
||||
public string? ThreadId => this._threadId;
|
||||
|
||||
public async Task AddMessagesAsync(IReadOnlyCollection<ChatMessage> messages, CancellationToken cancellationToken)
|
||||
{
|
||||
this._threadId ??= Guid.NewGuid().ToString();
|
||||
|
||||
var collection = vectorStore.GetCollection<string, ChatHistoryItem>("ChatHistory");
|
||||
await collection.EnsureCollectionExistsAsync(cancellationToken);
|
||||
|
||||
await collection.UpsertAsync(messages.Select(x => new ChatHistoryItem()
|
||||
{
|
||||
Key = this._threadId + x.MessageId,
|
||||
Timestamp = DateTimeOffset.UtcNow,
|
||||
ThreadId = this._threadId,
|
||||
SerializedMessage = JsonSerializer.Serialize(x),
|
||||
MessageText = x.Text
|
||||
}), cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<ChatMessage>> GetMessagesAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var collection = vectorStore.GetCollection<string, ChatHistoryItem>("ChatHistory");
|
||||
await collection.EnsureCollectionExistsAsync(cancellationToken);
|
||||
|
||||
var records = await collection
|
||||
.GetAsync(
|
||||
x => x.ThreadId == this._threadId, 10,
|
||||
new() { OrderBy = x => x.Descending(y => y.Timestamp) },
|
||||
cancellationToken)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
var messages = records
|
||||
.Select(x => JsonSerializer.Deserialize<ChatMessage>(x.SerializedMessage!)!)
|
||||
.ToList();
|
||||
messages.Reverse();
|
||||
return messages;
|
||||
}
|
||||
|
||||
public ValueTask<JsonElement?> SerializeStateAsync(JsonSerializerOptions? jsonSerializerOptions = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
// We have to serialize the thread id, so that on deserialization we can retrieve the messages using the same thread id.
|
||||
return new ValueTask<JsonElement?>(JsonSerializer.SerializeToElement(this._threadId));
|
||||
}
|
||||
|
||||
public ValueTask DeserializeStateAsync(JsonElement? serializedStoreState, JsonSerializerOptions? jsonSerializerOptions = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
// Here we can deserialize the thread id so that we can access the same messages as before the suspension.
|
||||
this._threadId = JsonSerializer.Deserialize<string>((JsonElement)serializedStoreState!);
|
||||
return new ValueTask();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The data structure used to store chat history items in the vector store.
|
||||
/// </summary>
|
||||
private sealed class ChatHistoryItem
|
||||
{
|
||||
[VectorStoreKey]
|
||||
public string? Key { get; set; }
|
||||
|
||||
[VectorStoreData]
|
||||
public string? ThreadId { get; set; }
|
||||
|
||||
[VectorStoreData]
|
||||
public DateTimeOffset? Timestamp { get; set; }
|
||||
|
||||
[VectorStoreData]
|
||||
public string? SerializedMessage { get; set; }
|
||||
|
||||
[VectorStoreData]
|
||||
public string? MessageText { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<LangVersion>12</LangVersion>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.OpenAI" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
<PackageReference Include="Microsoft.Extensions.AI.OpenAI" />
|
||||
<PackageReference Include="OpenTelemetry" />
|
||||
<PackageReference Include="OpenTelemetry.Exporter.Console" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Extensions.AI.Agents.OpenAI\Microsoft.Extensions.AI.Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Extensions.AI.Agents\Microsoft.Extensions.AI.Agents.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to create and use a simple AI agent with Azure OpenAI as the backend that logs telemetry using OpenTelemetry.
|
||||
|
||||
using System;
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Extensions.AI.Agents;
|
||||
using OpenAI;
|
||||
using OpenTelemetry;
|
||||
using OpenTelemetry.Trace;
|
||||
|
||||
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";
|
||||
|
||||
const string JokerName = "Joker";
|
||||
const string JokerInstructions = "You are good at telling jokes.";
|
||||
|
||||
// Enable telemetry
|
||||
AppContext.SetSwitch("Microsoft.Extensions.AI.Agents.EnableTelemetry", true);
|
||||
|
||||
// Create TracerProvider with console exporter
|
||||
// This will output the telemetry data to the console.
|
||||
string sourceName = Guid.NewGuid().ToString();
|
||||
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
|
||||
.AddSource(sourceName)
|
||||
.AddConsoleExporter()
|
||||
.Build();
|
||||
|
||||
// Create the agent, and enable OpenTelemetry instrumentation.
|
||||
AIAgent agent = new AzureOpenAIClient(
|
||||
new Uri(endpoint),
|
||||
new AzureCliCredential())
|
||||
.GetChatClient(deploymentName)
|
||||
.CreateAIAgent(JokerInstructions, JokerName)
|
||||
.WithOpenTelemetry(sourceName: sourceName);
|
||||
|
||||
// Invoke the agent and output the text result.
|
||||
Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate."));
|
||||
|
||||
// Invoke the agent with streaming support.
|
||||
await foreach (var update in agent.RunStreamingAsync("Tell me a joke about a pirate."))
|
||||
{
|
||||
Console.WriteLine(update);
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<LangVersion>12</LangVersion>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.OpenAI" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
<PackageReference Include="Microsoft.Extensions.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Extensions.AI.Agents.OpenAI\Microsoft.Extensions.AI.Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Extensions.AI.Agents\Microsoft.Extensions.AI.Agents.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,99 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
#pragma warning disable CA1812
|
||||
|
||||
// This sample shows how to use dependency injection to register an AIAgent and use it from a hosted service with a user input chat loop.
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.AI.Agents;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
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";
|
||||
|
||||
// Create a host builder that we will register services with and then run.
|
||||
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
|
||||
|
||||
// Add agent options to the service collection.
|
||||
const string JokerName = "Joker";
|
||||
const string JokerInstructions = "You are good at telling jokes.";
|
||||
builder.Services.AddSingleton(new ChatClientAgentOptions(JokerInstructions, JokerName));
|
||||
|
||||
// Add a chat client to the service collection.
|
||||
builder.Services.AddKeyedChatClient("AzureOpenAI", (sp) => new AzureOpenAIClient(
|
||||
new Uri(endpoint),
|
||||
new AzureCliCredential())
|
||||
.GetChatClient(deploymentName)
|
||||
.AsIChatClient());
|
||||
|
||||
// Add the AI agent to the service collection.
|
||||
builder.Services.AddSingleton<AIAgent>((sp) => new ChatClientAgent(
|
||||
chatClient: sp.GetRequiredKeyedService<IChatClient>("AzureOpenAI"),
|
||||
options: sp.GetRequiredService<ChatClientAgentOptions>()));
|
||||
|
||||
// Add a sample service that will use the agent to respond to user input.
|
||||
builder.Services.AddHostedService<SampleApp.SampleService>();
|
||||
|
||||
// Create a cancellation token and source to pass to the sample service that can
|
||||
// be used to signal shutdown of the application.
|
||||
CancellationTokenSource appShutdownCancellationTokenSource = new();
|
||||
CancellationToken appShutdownCancellationToken = appShutdownCancellationTokenSource.Token;
|
||||
builder.Services.AddKeyedSingleton("AppShutdown", appShutdownCancellationTokenSource);
|
||||
|
||||
// Build and run the host.
|
||||
using IHost host = builder.Build();
|
||||
await host.RunAsync(appShutdownCancellationToken).ConfigureAwait(false);
|
||||
|
||||
namespace SampleApp
|
||||
{
|
||||
/// <summary>
|
||||
/// A sample service that uses an AI agent to respond to user input.
|
||||
/// </summary>
|
||||
internal sealed class SampleService(AIAgent agent, [FromKeyedServices("AppShutdown")] CancellationTokenSource appShutdownCancellationTokenSource) : IHostedService
|
||||
{
|
||||
private AgentThread? _thread;
|
||||
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
// Create a thread that will be used for the entirety of the service lifetime so that the user can ask follow up questions.
|
||||
this._thread = agent.GetNewThread();
|
||||
_ = this.RunAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public async Task RunAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
// Delay a little to allow the service to finish starting.
|
||||
await Task.Delay(100, cancellationToken);
|
||||
|
||||
while (cancellationToken.IsCancellationRequested is false)
|
||||
{
|
||||
Console.WriteLine("\nAgent: Ask me to tell you a joke about a specific topic. To exit just press Ctrl+C or enter without any input.\n");
|
||||
Console.Write("> ");
|
||||
var input = Console.ReadLine();
|
||||
|
||||
// If the user enters no input, signal the application to shut down.
|
||||
if (string.IsNullOrWhiteSpace(input))
|
||||
{
|
||||
appShutdownCancellationTokenSource.Cancel();
|
||||
break;
|
||||
}
|
||||
|
||||
// Stream the output to the console as it is generated.
|
||||
await foreach (var update in agent.RunStreamingAsync(input, this._thread!, cancellationToken: cancellationToken))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
|
||||
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
# Getting started with agents
|
||||
|
||||
The getting started with agents samples demonstrate the fundamental concepts and functionalities
|
||||
of single agents and can be used with any agent type.
|
||||
|
||||
While the functionality can be used with any agent type, these samples use Azure OpenAI as the AI provider
|
||||
and use ChatCompletion as the type of service.
|
||||
|
||||
For other samples that demonstrate how to create and configure each type of agent that come with the agent framework,
|
||||
see the [How to create an agent for each provider](../AgentProviders/README.md) samples.
|
||||
|
||||
## Getting started with agents prerequisites
|
||||
|
||||
Before you begin, ensure you have the following prerequisites:
|
||||
|
||||
- .NET 8.0 SDK or later
|
||||
- Azure OpenAI service endpoint and deployment configured
|
||||
- Azure CLI installed and authenticated (for Azure credential authentication)
|
||||
|
||||
**Note**: This demo uses Azure CLI credentials for authentication. Make sure you're logged in with `az login` and have access to the Azure OpenAI resource. For more information, see the [Azure CLI documentation](https://learn.microsoft.com/cli/azure/authenticate-azure-cli-interactively).
|
||||
|
||||
## Samples
|
||||
|
||||
|Sample|Description|
|
||||
|---|---|
|
||||
|[Running a simple agent](./Agents_Step01_Running/)|This sample demonstrates how to create and run a basic agent with instructions|
|
||||
|[Multi-turn conversation with a simple agent](./Agents_Step02_MultiturnConversation/)|This sample demonstrates how to implement a multi-turn conversation with a simple agent|
|
||||
|[Using function tools with a simple agent](./Agents_Step03_UsingFunctionTools/)|This sample demonstrates how to use function tools with a simple agent|
|
||||
|[Using function tools with approvals](./Agents_Step04_UsingFunctionToolsWithApprovals/)|This sample demonstrates how to use function tools where approvals require human in the loop approvals before execution|
|
||||
|[Structured output with a simple agent](./Agents_Step05_StructuredOutput/)|This sample demonstrates how to use structured output with a simple agent|
|
||||
|[Persisted conversations with a simple agent](./Agents_Step06_PersistedConversations/)|This sample demonstrates how to persist conversations and reload them later. This is useful for cases where an agent is hosted in a stateless service|
|
||||
|[3rd party thread storage with a simple agent](./Agents_Step07_3rdPartyThreadStorage/)|This sample demonstrates how to store conversation history in a 3rd party storage solution|
|
||||
|[Telemetry with a simple agent](./Agents_Step08_Telemetry/)|This sample demonstrates how to add telemetry to a simple agent|
|
||||
|[Dependency injection with a simple agent](./Agents_Step09_DependencyInjection/)|This sample demonstrates how to add and resolve an agent with a dependency injection container|
|
||||
|
||||
## Running the samples from the console
|
||||
|
||||
To run the samples, navigate to the desired sample directory, e.g.
|
||||
|
||||
```powershell
|
||||
cd Agents_Step01_Running
|
||||
```
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
$env:AZURE_OPENAI_ENDPOINT="https://your-resource.openai.azure.com/" # Replace with your Azure OpenAI resource endpoint
|
||||
$env:AZURE_OPENAI_DEPLOYMENT_NAME="gpt-4o-mini" # Optional, defaults to gpt-4o-mini
|
||||
```
|
||||
|
||||
If the variables are not set, you will be prompted for the values when running the samples.
|
||||
|
||||
Execute the following command to build the sample:
|
||||
|
||||
```powershell
|
||||
dotnet build
|
||||
```
|
||||
|
||||
Execute the following command to run the sample:
|
||||
|
||||
```powershell
|
||||
dotnet run --no-build
|
||||
```
|
||||
|
||||
Or just build and run in one step:
|
||||
|
||||
```powershell
|
||||
dotnet run
|
||||
```
|
||||
|
||||
## Running the samples from Visual Studio
|
||||
|
||||
Open the solution in Visual Studio and set the desired sample project as the startup project. Then, run the project using the built-in debugger or by pressing `F5`.
|
||||
|
||||
You will be prompted for any required environment variables if they are not already set.
|
||||
@@ -1,41 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Shared.Samples;
|
||||
using OpenAI;
|
||||
using OpenAI.Chat;
|
||||
|
||||
namespace Custom;
|
||||
|
||||
/// <summary>
|
||||
/// End-to-end sample showing how to use a custom <see cref="OpenAIChatClientAgent"/>.
|
||||
/// </summary>
|
||||
public sealed class Custom_OpenAIChatClientAgent(ITestOutputHelper output) : AgentSample(output)
|
||||
{
|
||||
/// <summary>
|
||||
/// This will create an instance of <see cref="MyOpenAIChatClientAgent"/> and run it.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task RunCustomChatClientAgent()
|
||||
{
|
||||
var chatClient = new OpenAIClient(TestConfiguration.OpenAI.ApiKey).GetChatClient(TestConfiguration.OpenAI.ChatModelId);
|
||||
|
||||
var agent = new MyOpenAIChatClientAgent(chatClient);
|
||||
|
||||
var chatMessage = new UserChatMessage("Tell me a joke about a pirate.");
|
||||
var chatCompletion = await agent.RunAsync(chatMessage);
|
||||
|
||||
Console.WriteLine(chatCompletion.Content.Last().Text);
|
||||
}
|
||||
}
|
||||
|
||||
public class MyOpenAIChatClientAgent : OpenAIChatClientAgent
|
||||
{
|
||||
private const string JokerName = "Joker";
|
||||
private const string JokerInstructions = "You are good at telling jokes.";
|
||||
|
||||
public MyOpenAIChatClientAgent(ChatClient client, ILoggerFactory? loggerFactory = null) :
|
||||
base(client, instructions: JokerInstructions, name: JokerName, loggerFactory: loggerFactory)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Extensions.AI.Agents;
|
||||
using Microsoft.Shared.Samples;
|
||||
using OpenAI;
|
||||
|
||||
#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.
|
||||
|
||||
namespace Providers;
|
||||
|
||||
/// <summary>
|
||||
/// End-to-end sample showing how to use <see cref="AIAgent"/> with OpenAI Assistants.
|
||||
/// </summary>
|
||||
public sealed class AIAgent_With_OpenAIAssistant(ITestOutputHelper output) : AgentSample(output)
|
||||
{
|
||||
private const string JokerName = "Joker";
|
||||
private const string JokerInstructions = "You are good at telling jokes.";
|
||||
|
||||
[Fact]
|
||||
public async Task RunWithAssistant()
|
||||
{
|
||||
// Get a client to create server side agents with.
|
||||
var openAIClient = new OpenAIClient(TestConfiguration.OpenAI.ApiKey);
|
||||
|
||||
// Get the agent directly from OpenAIClient.
|
||||
AIAgent agent = openAIClient
|
||||
.GetAssistantClient()
|
||||
.CreateAIAgent(
|
||||
model: TestConfiguration.OpenAI.ChatModelId,
|
||||
name: JokerName,
|
||||
instructions: JokerInstructions
|
||||
);
|
||||
|
||||
// Start a new thread for the agent conversation.
|
||||
AgentThread thread = agent.GetNewThread();
|
||||
|
||||
// Respond to user input
|
||||
await RunAgentAsync("Tell me a joke about a pirate.");
|
||||
await RunAgentAsync("Now add some emojis to the joke.");
|
||||
|
||||
// Local function to invoke agent and display the conversation messages for the thread.
|
||||
async Task RunAgentAsync(string input)
|
||||
{
|
||||
Console.WriteLine(
|
||||
$"""
|
||||
User: {input}
|
||||
Assistant:
|
||||
{await agent.RunAsync(input, thread)}
|
||||
|
||||
""");
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
var assistantClient = openAIClient.GetAssistantClient();
|
||||
await assistantClient.DeleteThreadAsync(thread.ConversationId);
|
||||
await assistantClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
# Getting started
|
||||
|
||||
The getting started samples demonstrate the fundamental concepts and functionalities
|
||||
of the agent framework.
|
||||
|
||||
## Samples
|
||||
|
||||
|Sample|Description|
|
||||
|---|---|
|
||||
|[Agents](./Agents/README.md)|Getting started with agents|
|
||||
|[Agent Providers](./AgentProviders/README.md)|Getting started with creating agents using various providers|
|
||||
|[Agent Open Telemetry](./AgentOpenTelemetry/README.md)|Getting started with OpenTelemetry for agents|
|
||||
-125
@@ -1,125 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Text;
|
||||
using Azure.AI.Agents.Persistent;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.AI.Agents;
|
||||
using Microsoft.Shared.Samples;
|
||||
using OpenAI.Files;
|
||||
|
||||
namespace Steps;
|
||||
|
||||
/// <summary>
|
||||
/// Demonstrates how to use <see cref="ChatClientAgent"/> with code interpreter tools and file references.
|
||||
/// Shows uploading files to different providers and using them with code interpreter capabilities to analyze data and generate responses.
|
||||
/// </summary>
|
||||
public sealed class Step03_ChatClientAgent_UsingCodeInterpreterTools(ITestOutputHelper output) : AgentSample(output)
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(ChatClientProviders.AzureAIAgentsPersistent)]
|
||||
[InlineData(ChatClientProviders.OpenAIAssistant)]
|
||||
public async Task RunningWithFileReferenceAsync(ChatClientProviders provider)
|
||||
{
|
||||
var codeInterpreterTool = new HostedCodeInterpreterTool()
|
||||
{
|
||||
Inputs = [new HostedFileContent(await UploadFileAsync("Resources/groceries.txt", provider))]
|
||||
};
|
||||
|
||||
var agentOptions = new ChatClientAgentOptions(
|
||||
name: "HelpfulAssistant",
|
||||
instructions: "You are a helpful assistant.",
|
||||
tools: [codeInterpreterTool]);
|
||||
|
||||
// Create the server-side agent Id when applicable (depending on the provider).
|
||||
agentOptions.Id = await base.AgentCreateAsync(provider, agentOptions);
|
||||
|
||||
using var chatClient = base.GetChatClient(provider, agentOptions);
|
||||
|
||||
ChatClientAgent agent = new(chatClient, agentOptions);
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
|
||||
// Prompt which allows to verify that the data was processed from file correctly and current datetime is returned.
|
||||
const string Prompt = "Calculate the total number of items, identify the most frequently purchased item and return the result with today's datetime.";
|
||||
|
||||
var assistantOutput = new StringBuilder();
|
||||
var codeInterpreterOutput = new StringBuilder();
|
||||
|
||||
await foreach (var update in agent.RunStreamingAsync(Prompt, thread))
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(update.Text))
|
||||
{
|
||||
assistantOutput.Append(update.Text);
|
||||
}
|
||||
|
||||
if (update.RawRepresentation is ChatResponseUpdate chatUpdate && chatUpdate.RawRepresentation is not null)
|
||||
{
|
||||
codeInterpreterOutput.Append(GetCodeInterpreterOutput(chatUpdate.RawRepresentation, provider));
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine("Assistant Output:");
|
||||
Console.WriteLine(assistantOutput.ToString());
|
||||
|
||||
Console.WriteLine("Code interpreter Output:");
|
||||
Console.WriteLine(codeInterpreterOutput.ToString());
|
||||
|
||||
// Clean up the server-side agent after use when applicable (depending on the provider).
|
||||
await base.AgentCleanUpAsync(provider, agent, thread);
|
||||
}
|
||||
|
||||
#region private
|
||||
|
||||
/// <summary>
|
||||
/// Uploads a file to the specified chat client provider and returns the file ID.
|
||||
/// </summary>
|
||||
/// <param name="filePath">Path to the file to be uploaded.</param>
|
||||
/// <param name="provider">The chat client provider to use for uploading the file.</param>
|
||||
/// <returns>The ID of the uploaded file.</returns>
|
||||
/// <exception cref="NotSupportedException"></exception>
|
||||
private async Task<string> UploadFileAsync(string filePath, ChatClientProviders provider)
|
||||
{
|
||||
switch (provider)
|
||||
{
|
||||
case ChatClientProviders.OpenAIAssistant:
|
||||
var fileClient = new OpenAIFileClient(TestConfiguration.OpenAI.ApiKey);
|
||||
OpenAIFile openAIFileInfo = await fileClient.UploadFileAsync(filePath, FileUploadPurpose.Assistants);
|
||||
|
||||
return openAIFileInfo.Id;
|
||||
case ChatClientProviders.AzureAIAgentsPersistent:
|
||||
var persistentAgentsClient = new PersistentAgentsClient(TestConfiguration.AzureAI.Endpoint, new AzureCliCredential());
|
||||
PersistentAgentFileInfo persistentAgentFileInfo = await persistentAgentsClient.Files.UploadFileAsync(filePath, PersistentAgentFilePurpose.Agents);
|
||||
|
||||
return persistentAgentFileInfo.Id;
|
||||
|
||||
default:
|
||||
throw new NotSupportedException($"Client provider {provider} is not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Depending on the provider, different strategies are used to extract the code interpreter output from the response raw representation.
|
||||
/// </summary>
|
||||
/// <param name="rawRepresentation">Raw representation of the response containing code interpreter output.</param>
|
||||
/// <param name="provider">Provider of the chat client that is used to determine how to extract the output.</param>
|
||||
/// <returns>The code interpreter output as a string.</returns>
|
||||
private static string? GetCodeInterpreterOutput(object rawRepresentation, ChatClientProviders provider)
|
||||
=> provider switch
|
||||
{
|
||||
ChatClientProviders.OpenAIAssistant
|
||||
when rawRepresentation is OpenAI.Assistants.RunStepDetailsUpdate stepDetails => $"{stepDetails.CodeInterpreterInput}{string.Join(
|
||||
string.Empty,
|
||||
stepDetails.CodeInterpreterOutputs.SelectMany(l => l.Logs)
|
||||
)}",
|
||||
|
||||
ChatClientProviders.AzureAIAgentsPersistent
|
||||
when rawRepresentation is Azure.AI.Agents.Persistent.RunStepDetailsUpdate stepDetails => $"{stepDetails.CodeInterpreterInput}{string.Join(
|
||||
string.Empty,
|
||||
stepDetails.CodeInterpreterOutputs.OfType<RunStepDeltaCodeInterpreterLogOutput>().SelectMany(l => l.Logs)
|
||||
)}",
|
||||
_ => null,
|
||||
};
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Text;
|
||||
using Azure.AI.Agents.Persistent;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.AI.Agents;
|
||||
using Microsoft.Shared.Samples;
|
||||
using OpenAI.Files;
|
||||
using OpenAI.VectorStores;
|
||||
|
||||
namespace Steps;
|
||||
|
||||
/// <summary>
|
||||
/// Demonstrates how to use <see cref="ChatClientAgent"/> with file search tools and file references.
|
||||
/// Shows uploading files to different providers and using them with file search capabilities to retrieve and analyze information from documents.
|
||||
/// </summary>
|
||||
public sealed class Step07_ChatClientAgent_UsingFileSearchTools(ITestOutputHelper output) : AgentSample(output)
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(ChatClientProviders.AzureAIAgentsPersistent)]
|
||||
[InlineData(ChatClientProviders.OpenAIAssistant)]
|
||||
public async Task RunningWithFileReferenceAsync(ChatClientProviders provider)
|
||||
{
|
||||
// Upload a file to the specified provider.
|
||||
var fileId = await UploadFileAsync("Resources/employees.pdf", provider);
|
||||
|
||||
// Create a vector store for the uploaded file to enable file search capabilities.
|
||||
var vectorStoreId = await CreateVectorStoreAsync([fileId], provider);
|
||||
|
||||
// Create a file search tool that can access the vector store.
|
||||
var fileSearchTool = new HostedFileSearchTool()
|
||||
{
|
||||
Inputs = [new HostedVectorStoreContent(vectorStoreId)],
|
||||
};
|
||||
|
||||
var agentOptions = new ChatClientAgentOptions
|
||||
{
|
||||
Name = "FileSearchAssistant",
|
||||
Instructions = "You are a helpful assistant that can search through uploaded documents to answer questions. Use the file search tool to find relevant information from the uploaded files.",
|
||||
ChatOptions = new() { Tools = [fileSearchTool] }
|
||||
};
|
||||
|
||||
// Create the server-side agent Id when applicable (depending on the provider).
|
||||
agentOptions.Id = await base.AgentCreateAsync(provider, agentOptions);
|
||||
|
||||
using var chatClient = base.GetChatClient(provider, agentOptions);
|
||||
|
||||
ChatClientAgent agent = new(chatClient, agentOptions);
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
|
||||
// Prompt which allows to verify that the file search functionality works correctly with the uploaded document.
|
||||
const string Prompt = "Who is the youngest employee?";
|
||||
|
||||
var assistantOutput = new StringBuilder();
|
||||
|
||||
await foreach (var update in agent.RunStreamingAsync(Prompt, thread))
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(update.Text))
|
||||
{
|
||||
assistantOutput.Append(update.Text);
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine("Assistant Output:");
|
||||
Console.WriteLine(assistantOutput.ToString());
|
||||
|
||||
// Clean up the server-side agent after use when applicable (depending on the provider).
|
||||
await base.AgentCleanUpAsync(provider, agent, thread);
|
||||
}
|
||||
|
||||
#region private
|
||||
|
||||
/// <summary>
|
||||
/// Uploads a file to the specified chat client provider and returns the file ID.
|
||||
/// </summary>
|
||||
/// <param name="filePath">Path to the file to be uploaded.</param>
|
||||
/// <param name="provider">The chat client provider to use for uploading the file.</param>
|
||||
/// <returns>The ID of the uploaded file.</returns>
|
||||
/// <exception cref="NotSupportedException"></exception>
|
||||
private async Task<string> UploadFileAsync(string filePath, ChatClientProviders provider)
|
||||
{
|
||||
switch (provider)
|
||||
{
|
||||
case ChatClientProviders.OpenAIAssistant:
|
||||
var fileClient = new OpenAIFileClient(TestConfiguration.OpenAI.ApiKey);
|
||||
OpenAIFile openAIFileInfo = await fileClient.UploadFileAsync(filePath, FileUploadPurpose.Assistants);
|
||||
|
||||
return openAIFileInfo.Id;
|
||||
case ChatClientProviders.AzureAIAgentsPersistent:
|
||||
var persistentAgentsClient = new PersistentAgentsClient(TestConfiguration.AzureAI.Endpoint, new AzureCliCredential());
|
||||
PersistentAgentFileInfo persistentAgentFileInfo = await persistentAgentsClient.Files.UploadFileAsync(filePath, PersistentAgentFilePurpose.Agents);
|
||||
|
||||
return persistentAgentFileInfo.Id;
|
||||
|
||||
default:
|
||||
throw new NotSupportedException($"Client provider {provider} is not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
private Task<string> CreateVectorStoreAsync(IEnumerable<string> fileIds, ChatClientProviders provider)
|
||||
=> provider switch
|
||||
{
|
||||
ChatClientProviders.OpenAIAssistant => CreateVectorStoreOpenAIAssistantAsync(fileIds),
|
||||
ChatClientProviders.AzureAIAgentsPersistent => CreateVectorStoreAzureAIAgentsPersistentAsync(fileIds),
|
||||
_ => throw new NotSupportedException($"Client provider {provider} is not supported."),
|
||||
};
|
||||
|
||||
private async Task<string> CreateVectorStoreOpenAIAssistantAsync(IEnumerable<string> fileIds)
|
||||
{
|
||||
var vectorStoreClient = new VectorStoreClient(TestConfiguration.OpenAI.ApiKey);
|
||||
VectorStoreCreationOptions options = new();
|
||||
foreach (var fileId in fileIds)
|
||||
{
|
||||
options.FileIds.Add(fileId);
|
||||
}
|
||||
|
||||
var vectorStore = await vectorStoreClient.CreateVectorStoreAsync(waitUntilCompleted: true, options);
|
||||
return vectorStore.VectorStoreId;
|
||||
}
|
||||
|
||||
private async Task<string> CreateVectorStoreAzureAIAgentsPersistentAsync(IEnumerable<string> fileIds)
|
||||
{
|
||||
var client = new PersistentAgentsClient(TestConfiguration.AzureAI.Endpoint, new AzureCliCredential());
|
||||
var vectorStore = await client.VectorStores.CreateVectorStoreAsync(fileIds);
|
||||
return vectorStore.Value.Id;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
Reference in New Issue
Block a user