Rozšíření Azure AI pomocí nástrojů a spuštění místní funkce pomocí .NET
Začněte se sémantickým jádrem vytvořením jednoduché konzolové chatovací aplikace .NET 8. Aplikace se spustí místně a použije model OpenAI gpt-35-turbo
nasazený do účtu Azure OpenAI, ale pomocí nástroje rozšíří možnosti modelu, které bude volat místní funkci. Pomocí těchto kroků zřiďte Azure OpenAI a zjistěte, jak používat sémantické jádro.
Začněte se sadou .NET Azure OpenAI SDK vytvořením jednoduché konzolové chatovací aplikace .NET 8. Aplikace se spustí místně a použije model OpenAI gpt-35-turbo
nasazený do účtu Azure OpenAI, ale pomocí nástroje rozšíří možnosti modelu, které bude volat místní funkci. Pomocí těchto kroků zřiďte Azure OpenAI a zjistěte, jak používat sadu .NET Azure OpenAI SDK.
Požadavky
- .NET 8.0 SDK – Instalace sady .NET 8.0 SDK
- Předplatné Azure – Vytvoření předplatného zdarma
- Azure Developer CLI – Instalace nebo aktualizace Azure Developer CLI
- Přístup ke službě Azure OpenAI
- Ve Windows se vyžaduje PowerShell
v7+
. Pokud chcete ověřit svou verzi, spusťtepwsh
v terminálu. Měla by vrátit aktuální verzi. Pokud vrátí chybu, spusťte následující příkaz:dotnet tool update --global PowerShell
.
Nasazení prostředků Azure
Ujistěte se, že dodržujete požadavky , abyste měli přístup ke službě Azure OpenAI a rozhraní příkazového řádku Azure Developer CLI, a pak postupujte podle následujícího průvodce a nastavte ji s ukázkovou aplikací.
Klonování úložiště: dotnet/ai-samples
Z terminálu nebo příkazového řádku přejděte do adresáře Rychlý start .
Tím se zřídí prostředky Azure OpenAI. Vytvoření služby Azure OpenAI a nasazení modelu může trvat několik minut.
azd up
Poznámka:
Pokud už máte k dispozici službu Azure OpenAI, můžete nasazení přeskočit a použít tuto hodnotu v Program.cs, nejlépe z některého IConfiguration
.
Odstraňování potíží
Ve Windows se můžou po spuštění azd up
zobrazit následující chybové zprávy:
postprovision.ps1 není digitálně podepsán. Skript se v systému nespustí.
Skript postprovision.ps1 se spustí a nastaví tajné kódy uživatele .NET používané v aplikaci. Pokud se chcete této chybě vyhnout, spusťte následující příkaz PowerShellu:
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
Pak příkaz spusťte azd up
znovu.
Další možná chyba:
"pwsh" není rozpoznán jako interní nebo externí příkaz, operovatelný program nebo dávkový soubor. UPOZORNĚNÍ: "postprovision" hook selhal s ukončovacím kódem: '1', Cesta: '.\infra\post-script\postprovision.ps1'. : ukončovací kód: 1 Provádění bude pokračovat, protože ContinueOnError byl nastaven na hodnotu true.
Skript postprovision.ps1 se spustí a nastaví tajné kódy uživatele .NET používané v aplikaci. Pokud se chcete této chybě vyhnout, spusťte skript ručně pomocí následujícího příkazu PowerShellu:
.\infra\post-script\postprovision.ps1
Aplikace .NET AI teď mají nakonfigurované tajné kódy uživatelů a dají se testovat.
Vyzkoušejte si ukázku HikerAI Pro
- Z terminálu nebo příkazového řádku přejděte do
semantic-kernel\04-HikerAIPro
adresáře.
- Z terminálu nebo příkazového řádku přejděte do
azure-openai-sdk\04-HikerAIPro
adresáře.
Teď je čas vyzkoušet konzolovou aplikaci. Zadáním následujícího příkazu spusťte aplikaci:
dotnet run
Pokud se zobrazí chybová zpráva, že se nasazení prostředků Azure OpenAI nedokončily. Počkejte několik minut a zkuste to znovu.
Vysvětlení kódu
Naše aplikace používá Microsoft.SemanticKernel
balíček, který je k dispozici na NuGetu, k odesílání a přijímání požadavků do služby Azure OpenAI nasazené v Azure.
Celá aplikace je obsažena v souboru Program.cs . Prvních několik řádků kódu načte tajné kódy a konfigurační hodnoty, které byly nastaveny ve dotnet user-secrets
vámi během zřizování aplikace.
var config = new ConfigurationBuilder().AddUserSecrets<Program>().Build();
string endpoint = config["AZURE_OPENAI_ENDPOINT"];
string deployment = config["AZURE_OPENAI_GPT_NAME"];
string key = config["AZURE_OPENAI_KEY"];
Třída Kernel
usnadňuje požadavky a odpovědi pomocí AddAzureOpenAIChatCompletion
služby.
// Create a Kernel containing the Azure OpenAI Chat Completion Service
IKernelBuilder b = Kernel.CreateBuilder();
Kernel kernel = b
.AddAzureOpenAIChatCompletion(deployment, endpoint, key)
.Build();
Funkce ImportPluginFromFunctions
a CreateFromMethod
slouží k definování místní funkce, která bude volána modelem.
// Add a new plugin with a local .NET function that should be available to the AI model
// For convenience and clarity of into the code, this standalone local method handles tool call responses. It will fake a call to a weather API and return the current weather for the specified location.
kernel.ImportPluginFromFunctions("WeatherPlugin",
[
KernelFunctionFactory.CreateFromMethod(([Description("The city, e.g. Montreal, Sidney")] string location, string unit = null) =>
{
// Here you would call a weather API to get the weather for the location
return "Periods of rain or drizzle, 15 C";
}, "get_current_weather", "Get the current weather in a given location")
]);
kernel
Po vytvoření klienta poskytneme modelu další kontext přidáním systémové výzvy. Tím dáte modelu pokyn, jak se má během konverzace chovat. Všimněte si, jak se v příkazovém řádku systému zvýrazní počasí.
ChatHistory chatHistory = new("""
You are a hiking enthusiast who helps people discover fun hikes in their area. You are upbeat and friendly.
A good weather is important for a good hike. Only make recommendations if the weather is good or if people insist.
You introduce yourself when first saying hello. When helping people out, you always ask them
for this information to inform the hiking recommendation you provide:
1. Where they are located
2. What hiking intensity they are looking for
You will then provide three suggestions for nearby hikes that vary in length after you get that information.
You will also share an interesting fact about the local nature on the hikes when making a recommendation.
""");
Potom můžete do modelu přidat uživatelskou zprávu pomocí trychtonu AddUserMessage
.
Pokud chcete, aby model vygeneroval odpověď na základě systémové výzvy a požadavku uživatele, použijte GetChatMessageContentAsync
funkci.
chatHistory.AddUserMessage("""
Is the weather is good today for a hike?
If yes, I live in the greater Montreal area and would like an easy hike. I don't mind driving a bit to get there.
I don't want the hike to be over 10 miles round trip. I'd consider a point-to-point hike.
I want the hike to be as isolated as possible. I don't want to see many people.
I would like it to be as bug free as possible.
""");
Console.WriteLine($"{chatHistory.Last().Role} >>> {chatHistory.Last().Content}");
chatHistory.Add(await service.GetChatMessageContentAsync(chatHistory, new OpenAIPromptExecutionSettings() { MaxTokens = 400 }));
Console.WriteLine($"{chatHistory.Last().Role} >>> {chatHistory.Last().Content}");
Přizpůsobte si výzvu systému a uživatelskou zprávu, abyste viděli, jak model reaguje, aby vám pomohl najít trasu, která se vám bude líbit.
Vysvětlení kódu
Naše aplikace používá klientskou Azure.AI.OpenAI
sadu SDK, která je k dispozici na NuGetu, k odesílání a přijímání požadavků do služby Azure OpenAI nasazené v Azure.
Celá aplikace je obsažena v souboru Program.cs . Prvních několik řádků kódu načte tajné kódy a konfigurační hodnoty, které byly nastaveny ve dotnet user-secrets
vámi během zřizování aplikace.
// == Retrieve the local secrets saved during the Azure deployment ==========
var config = new ConfigurationBuilder().AddUserSecrets<Program>().Build();
string openAIEndpoint = config["AZURE_OPENAI_ENDPOINT"];
string openAIDeploymentName = config["AZURE_OPENAI_GPT_NAME"];
string openAiKey = config["AZURE_OPENAI_KEY"];
// == Creating the AIClient ==========
var endpoint = new Uri(openAIEndpoint);
var credentials = new AzureKeyCredential(openAiKey);
Třída OpenAIClient
usnadňuje požadavky a odpovědi. ChatCompletionOptions
určuje parametry, jak bude model reagovat. Všimněte si, jak se vlastnost Tools používá k přidání definice.
var openAIClient = new OpenAIClient(endpoint, credentials);
var completionOptions = new ChatCompletionsOptions
{
MaxTokens = 400,
Temperature = 1f,
FrequencyPenalty = 0.0f,
PresencePenalty = 0.0f,
NucleusSamplingFactor = 0.95f, // Top P
DeploymentName = openAIDeploymentName,
Tools = { getWeather }
};
Třída ChatCompletionsFunctionToolDefinition
se používá k definování místní funkce, která bude volána modelem.
var getWeather = new ChatCompletionsFunctionToolDefinition()
{
Name = "get_current_weather",
Description = "Get the current weather in a given location",
Parameters = BinaryData.FromObjectAsJson(
new
{
Type = "object",
Properties = new
{
Location = new
{
Type = "string",
Description = "The city, e.g. Montreal, Sidney",
},
Unit = new
{
Type = "string",
Enum = new[] { "celsius", "fahrenheit" },
}
},
Required = new[] { "location" },
},
new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }),
};
OpenAIClient
Po vytvoření klienta poskytneme modelu další kontext přidáním systémové výzvy. Tím dáte modelu pokyn, jak se má během konverzace chovat. Všimněte si, jak se v příkazovém řádku systému zvýrazní počasí.
var systemPrompt =
"""
You are a hiking enthusiast who helps people discover fun hikes in their area. You are upbeat and friendly.
A good weather is important for a good hike. Only make recommendations if the weather is good or if people insist.
You introduce yourself when first saying hello. When helping people out, you always ask them
for this information to inform the hiking recommendation you provide:
1. Where they are located
2. What hiking intensity they are looking for
You will then provide three suggestions for nearby hikes that vary in length after you get that information.
You will also share an interesting fact about the local nature on the hikes when making a recommendation.
""";
completionOptions.Messages.Add(new ChatRequestSystemMessage(systemPrompt));
Pak můžete do modelu přidat zprávu uživatele pomocí ChatRequestUserMessage
třídy.
Pro usnadnění a srozumitelnost kódu tato samostatná místní metoda zpracovává odpovědi na volání nástroje. Zfalšuje volání rozhraní API pro počasí a vrátí aktuální počasí pro zadanou polohu.
ChatRequestToolMessage GetToolCallResponseMessage(ChatCompletionsToolCall toolCall)
{
var functionToolCall = toolCall as ChatCompletionsFunctionToolCall;
if (functionToolCall?.Name == getWeather.Name)
{
string unvalidatedArguments = functionToolCall.Arguments;
var functionResultData = (object)null;
// == Here call a weather API to get the weather for specified the location ==========
functionResultData = "Periods of rain or drizzle, 15 C";
return new ChatRequestToolMessage(functionResultData.ToString(), toolCall.Id);
}
else
{
throw new NotImplementedException();
}
}
Pokud chcete, aby model vygeneroval odpověď na základě systémové výzvy a požadavku uživatele, použijte GetChatCompletionsAsync
funkci.
string hikeRequest = """
Is the weather is good today for a hike?
If yes, I live in the greater Montreal area and would like an easy hike. I don't mind driving a bit to get there.
I don't want the hike to be over 10 miles round trip. I'd consider a point-to-point hike.
I want the hike to be as isolated as possible. I don't want to see many people.
I would like it to be as bug free as possible.
""";
Console.WriteLine($"\n\nUser >>> {hikeRequest}");
completionOptions.Messages.Add(new ChatRequestUserMessage(hikeRequest));
response = await openAIClient.GetChatCompletionsAsync(completionOptions);
Teď je potřeba prozkoumat odpověď. Pokud odpověď obsahuje ToolCalls
, metoda deklaruje dříve zpracovat ji a pokračovat v konverzaci. Je důležité si uvědomit, že všechny zprávy ChatRequestAssistantMessage
se přidají do historie konverzací. To je důležité pro zachování kontextu konverzace.
ChatChoice responseChoice = response.Choices[0];
if (responseChoice.FinishReason == CompletionsFinishReason.ToolCalls)
{
// == Include the FunctionCall message in the conversation history ==========
completionOptions.Messages.Add(new ChatRequestAssistantMessage(responseChoice.Message));
// == Add a new tool message for each tool call that is resolved ==========
foreach (ChatCompletionsToolCall toolCall in responseChoice.Message.ToolCalls)
{
var ToolCallMsg = GetToolCallResponseMessage(toolCall);
completionOptions.Messages.Add(ToolCallMsg);
}
// == Retrieve the answer from HikeAI Pro ==========
response = await openAIClient.GetChatCompletionsAsync(completionOptions);
}
assistantResponse = response.Choices[0].Message;
Console.WriteLine($"\n\nAssistant >>> {assistantResponse.Content}");
Přizpůsobte si výzvu systému a uživatelskou zprávu, abyste viděli, jak model reaguje, aby vám pomohl najít trasu, která se vám bude líbit.
Vyčištění prostředků
Pokud už ukázkovou aplikaci nebo prostředky nepotřebujete, odeberte odpovídající nasazení a všechny prostředky.
azd down
Další kroky
Váš názor
https://aka.ms/ContentUserFeedback.
Připravujeme: V průběhu roku 2024 budeme postupně vyřazovat problémy z GitHub coby mechanismus zpětné vazby pro obsah a nahrazovat ho novým systémem zpětné vazby. Další informace naleznete v tématu:Odeslat a zobrazit názory pro