mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
.NET: Add Ollama and custom agent samples, plus ONNX improvements (#639)
* Add ollama and custom agent samples, plus onnx improvements * Update dotnet/samples/GettingStarted/AgentProviders/Agent_With_CustomImplementation/Program.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Address PR comments. * Address pr comments. --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
Unverified
parent
8c5cba5826
commit
b2a6b64d72
@@ -79,6 +79,7 @@
|
||||
<PackageVersion Include="ModelContextProtocol" Version="0.3.0-preview.4" />
|
||||
<!-- Inference SDKs -->
|
||||
<PackageVersion Include="Microsoft.ML.OnnxRuntimeGenAI" Version="0.9.0" />
|
||||
<PackageVersion Include="OllamaSharp" Version="5.3.6" />
|
||||
<!-- Identity -->
|
||||
<PackageVersion Include="Microsoft.Identity.Client.Extensions.Msal" Version="4.74.1" />
|
||||
<!-- Workflows -->
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_AzureFoundry/Agent_With_AzureFoundry.csproj" />
|
||||
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_AzureOpenAIChatCompletion/Agent_With_AzureOpenAIChatCompletion.csproj" />
|
||||
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_AzureOpenAIResponses/Agent_With_AzureOpenAIResponses.csproj" />
|
||||
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_CustomImplementation/Agent_With_CustomImplementation.csproj" />
|
||||
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_Ollama/Agent_With_Ollama.csproj" />
|
||||
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_ONNX/Agent_With_ONNX.csproj" />
|
||||
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_OpenAIChatCompletion/Agent_With_OpenAIChatCompletion.csproj" />
|
||||
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_OpenAIResponses/Agent_With_OpenAIResponses.csproj" />
|
||||
@@ -43,6 +45,7 @@
|
||||
<Project Path="samples/GettingStarted/Agents/Agent_Step10_AsMcpTool/Agent_Step10_AsMcpTool.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/Samples/GettingStarted/AgentWithOpenAI/">
|
||||
<File Path="samples/GettingStarted/AgentWithOpenAI/README.md" />
|
||||
<Project Path="samples/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step01_Running/Agent_OpenAI_Step01_Running.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/Samples/GettingStarted/Telemetry/">
|
||||
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
<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\Microsoft.Extensions.AI.Agents.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows all the required steps to create a fully custom agent implementation.
|
||||
// In this case the agent doesn't use AI at all, and simply parrots back the user input in upper case.
|
||||
// You can however, build a fully custom agent that uses AI in any way you want.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.AI.Agents;
|
||||
using SampleApp;
|
||||
|
||||
AIAgent agent = new UpperCaseParrotAgent();
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
namespace SampleApp
|
||||
{
|
||||
// Custom agent that parrot's the user input back in upper case.
|
||||
internal sealed class UpperCaseParrotAgent : AIAgent
|
||||
{
|
||||
public override async Task<AgentRunResponse> RunAsync(IReadOnlyCollection<ChatMessage> messages, AgentThread? thread = null, AgentRunOptions? options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
// Create a thread if the user didn't supply one.
|
||||
thread ??= this.GetNewThread();
|
||||
|
||||
// Clone the input messages and turn them into response messages with upper case text.
|
||||
List<ChatMessage> responseMessages = CloneAndToUpperCase(messages, this.DisplayName).ToList();
|
||||
|
||||
// Notify the thread of the input and output messages.
|
||||
await NotifyThreadOfNewMessagesAsync(thread, messages, cancellationToken);
|
||||
await NotifyThreadOfNewMessagesAsync(thread, responseMessages, cancellationToken);
|
||||
|
||||
return new AgentRunResponse
|
||||
{
|
||||
AgentId = this.Id,
|
||||
ResponseId = Guid.NewGuid().ToString(),
|
||||
Messages = responseMessages
|
||||
};
|
||||
}
|
||||
|
||||
public override async IAsyncEnumerable<AgentRunResponseUpdate> RunStreamingAsync(IReadOnlyCollection<ChatMessage> messages, AgentThread? thread = null, AgentRunOptions? options = null, [EnumeratorCancellation] CancellationToken cancellationToken = default)
|
||||
{
|
||||
// Create a thread if the user didn't supply one.
|
||||
thread ??= this.GetNewThread();
|
||||
|
||||
// Clone the input messages and turn them into response messages with upper case text.
|
||||
List<ChatMessage> responseMessages = CloneAndToUpperCase(messages, this.DisplayName).ToList();
|
||||
|
||||
// Notify the thread of the input and output messages.
|
||||
await NotifyThreadOfNewMessagesAsync(thread, messages, cancellationToken);
|
||||
await NotifyThreadOfNewMessagesAsync(thread, responseMessages, cancellationToken);
|
||||
|
||||
foreach (var message in responseMessages)
|
||||
{
|
||||
yield return new AgentRunResponseUpdate
|
||||
{
|
||||
AgentId = this.Id,
|
||||
AuthorName = this.DisplayName,
|
||||
Role = ChatRole.Assistant,
|
||||
Contents = message.Contents,
|
||||
ResponseId = Guid.NewGuid().ToString(),
|
||||
MessageId = Guid.NewGuid().ToString()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<ChatMessage> CloneAndToUpperCase(IReadOnlyCollection<ChatMessage> messages, string agentName) => messages.Select(x =>
|
||||
{
|
||||
// Clone the message and update its author to be the agent.
|
||||
var messageClone = x.Clone();
|
||||
messageClone.Role = ChatRole.Assistant;
|
||||
messageClone.MessageId = Guid.NewGuid().ToString();
|
||||
messageClone.AuthorName = agentName;
|
||||
|
||||
// Clone and convert any text content to upper case.
|
||||
messageClone.Contents = x.Contents.Select(c => c switch
|
||||
{
|
||||
TextContent tc => new TextContent(tc.Text.ToUpperInvariant())
|
||||
{
|
||||
AdditionalProperties = tc.AdditionalProperties,
|
||||
Annotations = tc.Annotations,
|
||||
RawRepresentation = tc.RawRepresentation
|
||||
},
|
||||
_ => c
|
||||
}).ToList();
|
||||
|
||||
return messageClone;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
# Prerequisites
|
||||
|
||||
This sample has no prerequisites.
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to create and use a simple AI agent with ONNX as the backend.
|
||||
// WARNING: ONNX doesn't support function calling, so any function tools passed to the agent will be ignored.
|
||||
|
||||
using System;
|
||||
using Microsoft.Extensions.AI.Agents;
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
# Prerequisites
|
||||
|
||||
WARNING: ONNX doesn't support function calling, so any function tools passed to the agent will be ignored.
|
||||
|
||||
Before you begin, ensure you have the following prerequisites:
|
||||
|
||||
- .NET 8.0 SDK or later
|
||||
- An ONNX model downloaded to your machine
|
||||
|
||||
You can download an ONNX model from hugging face, using git clone:
|
||||
|
||||
```powershell
|
||||
git clone https://huggingface.co/microsoft/Phi-4-mini-instruct-onnx
|
||||
```
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
|
||||
+20
@@ -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="OllamaSharp" />
|
||||
</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 Ollama as the backend.
|
||||
|
||||
using System;
|
||||
using Microsoft.Extensions.AI.Agents;
|
||||
using OllamaSharp;
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("OLLAMA_ENDPOINT") ?? throw new InvalidOperationException("OLLAMA_ENDPOINT is not set.");
|
||||
var modelName = Environment.GetEnvironmentVariable("OLLAMA_MODEL_NAME") ?? throw new InvalidOperationException("OLLAMA_MODEL_NAME is not set.");
|
||||
|
||||
const string JokerName = "Joker";
|
||||
const string JokerInstructions = "You are good at telling jokes.";
|
||||
|
||||
// Get a chat client for Ollama and use it to construct an AIAgent.
|
||||
using OllamaApiClient chatClient = new(new Uri(endpoint), modelName);
|
||||
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,34 @@
|
||||
# Prerequisites
|
||||
|
||||
Before you begin, ensure you have the following prerequisites:
|
||||
|
||||
- .NET 8.0 SDK or later
|
||||
- Docker installed and running on your machine
|
||||
- An Ollama model downloaded into Ollama
|
||||
|
||||
To download and start Ollama on Docker using CPU, run the following command in your terminal.
|
||||
|
||||
```powershell
|
||||
docker run -d -v "c:\temp\ollama:/root/.ollama" -p 11434:11434 --name ollama ollama/ollama
|
||||
```
|
||||
|
||||
To download and start Ollama on Docker using GPU, run the following command in your terminal.
|
||||
|
||||
```powershell
|
||||
docker run -d --gpus=all -v "c:\temp\ollama:/root/.ollama" -p 11434:11434 --name ollama ollama/ollama
|
||||
```
|
||||
|
||||
After the container has started, launch a Terminal window for the docker container, e.g. if using docker desktop, choose Open in Terminal from actions.
|
||||
|
||||
From this terminal download the required models, e.g. here we are downloading the phi3 model.
|
||||
|
||||
```text
|
||||
ollama pull gpt-oss
|
||||
```
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
$env:OLLAMA_ENDPOINT="http://localhost:11434"
|
||||
$env:OLLAMA_MODEL_NAME="gpt-oss"
|
||||
```
|
||||
@@ -9,6 +9,7 @@ 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|
|
||||
@@ -17,6 +18,8 @@ See the README.md for each sample for the prerequisites for that sample.
|
||||
|[Creating an AIAgent with AzureFoundry](./Agent_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](./Agent_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](./Agent_With_AzureOpenAIResponses/)|This sample demonstrates how to create an AIAgent using Azure OpenAI Responses as the underlying inference service|
|
||||
|[Creating an AIAgent with a custom implementation](./Agent_With_CustomImplementation/)|This sample demonstrates how to create an AIAgent with a custom implementation|
|
||||
|[Creating an AIAgent with Ollama](./Agent_With_Ollama/)|This sample demonstrates how to create an AIAgent using Ollama as the underlying inference service|
|
||||
|[Creating an AIAgent with ONNX](./Agent_With_ONNX/)|This sample demonstrates how to create an AIAgent using ONNX as the underlying inference service|
|
||||
|[Creating an AIAgent with OpenAI ChatCompletion](./Agent_With_OpenAIChatCompletion/)|This sample demonstrates how to create an AIAgent using OpenAI ChatCompletion as the underlying inference service|
|
||||
|[Creating an AIAgent with OpenAI Responses](./Agent_With_OpenAIResponses/)|This sample demonstrates how to create an AIAgent using OpenAI Responses as the underlying inference service|
|
||||
|
||||
@@ -7,6 +7,8 @@ of the agent framework.
|
||||
|
||||
|Sample|Description|
|
||||
|---|---|
|
||||
|[Agents](./Agents/README.md)|Getting started with agents|
|
||||
|[Agents](./Agents/README.md)|Step by step instructions for 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|
|
||||
|[Agent With OpenAI exchange types](./AgentWithOpenAI/README.md)|Using OpenAI exchange types with agents|
|
||||
|[Workflow](./Workflow/README.md)|Getting started with Workflow|
|
||||
|
||||
Reference in New Issue
Block a user