Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Fontos
Ez egy archivált dokumentum.
Fontos
Ez a funkció a kísérleti fázisban van, de már nem tart fenn. Csere esetén tekintse meg a Csoportos csevegés vezénylését és a migrálási útmutatót az AgentChatből a csoportos csevegés vezénylésére.
Áttekintés
Ebben a mintában bemutatjuk, hogyan használhatjuk a AgentGroupChat a felhasználó által megadott tartalom áttekintésén és átírásán dolgozó két különböző ügynök együttműködésének összehangolására. Minden ügynökhöz külön szerepkör van hozzárendelve:
- Véleményező: Vélemények és útmutatást ad az Írónak.
- Író: Frissíti a felhasználói tartalmat a véleményező bemenete alapján.
A megközelítés lépésről lépésre bontva lesz, hogy a kódolási folyamat főbb részeit jól megvilágítsa.
Első lépések
A funkciókódolás előtt győződjön meg arról, hogy a fejlesztési környezet teljesen be van állítva és konfigurálva van.
Jótanács
Ez a minta egy opcionális szövegfájlt használ a feldolgozás részeként. Ha használni szeretné, letöltheti itt. Helyezze a fájlt a kód munkakönyvtárába.
Először hozzon létre egy konzolprojektet. Ezután adja meg a következő csomaghivatkozásokat, hogy az összes szükséges függőség elérhető legyen.
Ha csomagfüggőségeket szeretne hozzáadni a parancssorból, használja a dotnet következő parancsot:
dotnet add package Azure.Identity
dotnet add package Microsoft.Extensions.Configuration
dotnet add package Microsoft.Extensions.Configuration.Binder
dotnet add package Microsoft.Extensions.Configuration.UserSecrets
dotnet add package Microsoft.Extensions.Configuration.EnvironmentVariables
dotnet add package Microsoft.SemanticKernel.Connectors.AzureOpenAI
dotnet add package Microsoft.SemanticKernel.Agents.Core --prerelease
Ha NuGet-csomagokat kezel a Visual Studióban, ellenőrizze, hogy
Include prereleasevan-e bejelölve.
A projektfájlnak (.csproj) a következő PackageReference definíciókat kell tartalmaznia:
<ItemGroup>
<PackageReference Include="Azure.Identity" Version="<stable>" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="<stable>" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="<stable>" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="<stable>" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="<stable>" />
<PackageReference Include="Microsoft.SemanticKernel.Agents.Core" Version="<latest>" />
<PackageReference Include="Microsoft.SemanticKernel.Connectors.AzureOpenAI" Version="<latest>" />
</ItemGroup>
A Agent Framework kísérleti jellegű, és figyelmeztetések elnyomását igényli. Ez megadható a projektfájl tulajdonságaként (.csproj).
<PropertyGroup>
<NoWarn>$(NoWarn);CA2007;IDE1006;SKEXP0001;SKEXP0110;OPENAI001</NoWarn>
</PropertyGroup>
Jótanács
Ez a minta egy opcionális szövegfájlt használ a feldolgozás részeként. Ha használni szeretné, letöltheti itt. Helyezze a fájlt a kód munkakönyvtárába.
Először telepítse a Szemantic Kernel Python-csomagot.
pip install semantic-kernel
Ezután adja hozzá a szükséges importot.
import asyncio
import os
from semantic_kernel import Kernel
from semantic_kernel.agents import AgentGroupChat, ChatCompletionAgent
from semantic_kernel.agents.strategies import (
KernelFunctionSelectionStrategy,
KernelFunctionTerminationStrategy,
)
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion
from semantic_kernel.contents import ChatHistoryTruncationReducer
from semantic_kernel.functions import KernelFunctionFromPrompt
A funkció jelenleg nem érhető el a Javában.
Konfiguráció
Ez a minta konfigurációs beállítást igényel a távoli szolgáltatásokhoz való csatlakozáshoz. Meg kell adnia az OpenAI vagy az Azure OpenAI beállításait.
# OpenAI
dotnet user-secrets set "OpenAISettings:ApiKey" "<api-key>"
dotnet user-secrets set "OpenAISettings:ChatModel" "gpt-4o"
# Azure OpenAI
dotnet user-secrets set "AzureOpenAISettings:ApiKey" "<api-key>" # Not required if using token-credential
dotnet user-secrets set "AzureOpenAISettings:Endpoint" "<model-endpoint>"
dotnet user-secrets set "AzureOpenAISettings:ChatModelDeployment" "gpt-4o"
A rendszer az alábbi osztályt használja az összes ügynök-példában. A megfelelő működés érdekében mindenképpen vegye fel a projektbe. Ez az osztály alapvető összetevőként szolgál az alábbi példákhoz.
using System.Reflection;
using Microsoft.Extensions.Configuration;
namespace AgentsSample;
public class Settings
{
private readonly IConfigurationRoot configRoot;
private AzureOpenAISettings azureOpenAI;
private OpenAISettings openAI;
public AzureOpenAISettings AzureOpenAI => this.azureOpenAI ??= this.GetSettings<Settings.AzureOpenAISettings>();
public OpenAISettings OpenAI => this.openAI ??= this.GetSettings<Settings.OpenAISettings>();
public class OpenAISettings
{
public string ChatModel { get; set; } = string.Empty;
public string ApiKey { get; set; } = string.Empty;
}
public class AzureOpenAISettings
{
public string ChatModelDeployment { get; set; } = string.Empty;
public string Endpoint { get; set; } = string.Empty;
public string ApiKey { get; set; } = string.Empty;
}
public TSettings GetSettings<TSettings>() =>
this.configRoot.GetRequiredSection(typeof(TSettings).Name).Get<TSettings>()!;
public Settings()
{
this.configRoot =
new ConfigurationBuilder()
.AddEnvironmentVariables()
.AddUserSecrets(Assembly.GetExecutingAssembly(), optional: true)
.Build();
}
}
A mintakód futtatásához szükséges megfelelő konfiguráció használatának leggyorsabb módja egy .env fájl létrehozása a projekt gyökerénél (ahol a szkript fut). A minta használatához elérhető Azure OpenAI- vagy OpenAI-erőforrásokra van szükség.
Állítsa be a következő beállításokat az .env fájlban, akár az Azure OpenAI, akár az OpenAI esetén:
AZURE_OPENAI_API_KEY="..."
AZURE_OPENAI_ENDPOINT="https://<resource-name>.openai.azure.com/"
AZURE_OPENAI_CHAT_DEPLOYMENT_NAME="..."
AZURE_OPENAI_API_VERSION="..."
OPENAI_API_KEY="sk-..."
OPENAI_ORG_ID=""
OPENAI_CHAT_MODEL_ID=""
A konfigurálás után a megfelelő AI-szolgáltatásosztályok felveszik a szükséges változókat, és a példányosítás során használják őket.
A funkció jelenleg nem érhető el a Javában.
Kódolás
A minta kódolási folyamata a következőket foglalja magában:
- Beállítás – Beállítások inicializálása és a beépülő modul.
-
AgentDefiníció – Készítse el a kétChatCompletionAgentpéldányt (Véleményező és Író). -
beszélgetés meghatározás – Hozd létre a
AgentGroupChatés a kapcsolódó stratégiákat. - A csevegési hurok – Írja meg a felhasználói/ügynöki interakciót hajtó hurkot.
A teljes példakód az Utolsó szakaszban található. A teljes megvalósításhoz tekintse meg ezt a szakaszt.
Beállítás
Mielőtt bármilyen ChatCompletionAgent-t létrehoznánk, inicializálni kell a konfigurációs beállításokat, a beépülő modulokat és a Kernel-et.
Példányosítsa a Settings osztályt, amelyre az előző Konfiguráció szakasz hivatkozik.
Settings settings = new();
A funkció jelenleg nem érhető el a Javában.
Most kezdje el egy Kernel példány inicializálását egy IChatCompletionService segítségével.
IKernelBuilder builder = Kernel.CreateBuilder();
builder.AddAzureOpenAIChatCompletion(
settings.AzureOpenAI.ChatModelDeployment,
settings.AzureOpenAI.Endpoint,
new AzureCliCredential());
Kernel kernel = builder.Build();
A kernelobjektum inicializálása:
kernel = Kernel()
A funkció jelenleg nem érhető el a Javában.
Hozzunk létre egy második Kernel-példányt is klónozási keresztül, és adjunk hozzá egy beépülő modult, amely lehetővé teszi, hogy a felülvizsgálat frissített tartalmat helyezzen el a vágólapon.
Kernel toolKernel = kernel.Clone();
toolKernel.Plugins.AddFromType<ClipboardAccess>();
A funkció jelenleg nem érhető el a Javában.
A vágólap plugin a minta részeként definiálható.
private sealed class ClipboardAccess
{
[KernelFunction]
[Description("Copies the provided content to the clipboard.")]
public static void SetClipboard(string content)
{
if (string.IsNullOrWhiteSpace(content))
{
return;
}
using Process clipProcess = Process.Start(
new ProcessStartInfo
{
FileName = "clip",
RedirectStandardInput = true,
UseShellExecute = false,
});
clipProcess.StandardInput.Write(content);
clipProcess.StandardInput.Close();
}
}
A funkció jelenleg nem érhető el a Javában.
Ügynökdefiníció
Deklaráljuk az ügynökneveket const, hogy hivatkozni lehessen rájuk AgentGroupChat stratégiákban:
const string ReviewerName = "Reviewer";
const string WriterName = "Writer";
Az ügynök nevét "Véleményező" és "Író" néven deklaráljuk.
REVIEWER_NAME = "Reviewer"
COPYWRITER_NAME = "Writer"
A funkció jelenleg nem érhető el a Javában.
A Véleményező ügynök meghatározása az Útmutató: Csevegés-befejező ügynök során feltárt mintát használja.
Itt a véleményezőnek az a feladata, hogy válaszoljon a felhasználói bemenetre, irányt adjon az Íróügynöknek , és ellenőrizze az Íróügynök eredményét.
ChatCompletionAgent agentReviewer =
new()
{
Name = ReviewerName,
Instructions =
"""
Your responsibility is to review and identify how to improve user provided content.
If the user has providing input or direction for content already provided, specify how to address this input.
Never directly perform the correction or provide example.
Once the content has been updated in a subsequent response, you will review the content again until satisfactory.
Always copy satisfactory content to the clipboard using available tools and inform user.
RULES:
- Only identify suggestions that are specific and actionable.
- Verify previous suggestions have been addressed.
- Never repeat previous suggestions.
""",
Kernel = toolKernel,
Arguments =
new KernelArguments(
new AzureOpenAIPromptExecutionSettings()
{
FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()
})
};
agent_reviewer = ChatCompletionAgent(
kernel=kernel,
name=REVIEWER_NAME,
instructions="""
Your responsibility is to review and identify how to improve user provided content.
If the user has provided input or direction for content already provided, specify how to address this input.
Never directly perform the correction or provide an example.
Once the content has been updated in a subsequent response, review it again until it is satisfactory.
RULES:
- Only identify suggestions that are specific and actionable.
- Verify previous suggestions have been addressed.
- Never repeat previous suggestions.
""",
)
A funkció jelenleg nem érhető el a Javában.
Az Íróügynök hasonló, de nem követeli meg a végrehajtási beállítások specifikációját, mivel nincs beépülő modullal konfigurálva.
Itt az Író egy egycélú feladatot kap, kövesse az irányt, és írja át a tartalmat.
ChatCompletionAgent agentWriter =
new()
{
Name = WriterName,
Instructions =
"""
Your sole responsibility is to rewrite content according to review suggestions.
- Always apply all review direction.
- Always revise the content in its entirety without explanation.
- Never address the user.
""",
Kernel = kernel,
};
Az Író ügynök hasonló. Egy célfeladatot kap, követi az irányt, és újraírja a tartalmat.
agent_writer = ChatCompletionAgent(
kernel=kernel,
name=WRITER_NAME,
instructions="""
Your sole responsibility is to rewrite content according to review suggestions.
- Always apply all review directions.
- Always revise the content in its entirety without explanation.
- Never address the user.
""",
)
A funkció jelenleg nem érhető el a Javában.
A csevegés meghatározása
A AgentGroupChat meghatározásához figyelembe kell venni a Agent forduló kiválasztására vonatkozó stratégiákat, és meg kell határozni, hogy mikor kell kilépni a csevegési ciklusból. Mindkét szempont esetében meghatározunk egy kernel-parancssori függvényt.
Az első, aki átgondolja a Agent kiválasztását:
A AgentGroupChat.CreatePromptFunctionForStrategy használata kényelmes mechanizmust biztosít az üzenetparaméter HTML-kódolás elkerüléséhez.
KernelFunction selectionFunction =
AgentGroupChat.CreatePromptFunctionForStrategy(
$$$"""
Examine the provided RESPONSE and choose the next participant.
State only the name of the chosen participant without explanation.
Never choose the participant named in the RESPONSE.
Choose only from these participants:
- {{{ReviewerName}}}
- {{{WriterName}}}
Always follow these rules when choosing the next participant:
- If RESPONSE is user input, it is {{{ReviewerName}}}'s turn.
- If RESPONSE is by {{{ReviewerName}}}, it is {{{WriterName}}}'s turn.
- If RESPONSE is by {{{WriterName}}}, it is {{{ReviewerName}}}'s turn.
RESPONSE:
{{$lastmessage}}
""",
safeParameterNames: "lastmessage");
selection_function = KernelFunctionFromPrompt(
function_name="selection",
prompt=f"""
Examine the provided RESPONSE and choose the next participant.
State only the name of the chosen participant without explanation.
Never choose the participant named in the RESPONSE.
Choose only from these participants:
- {REVIEWER_NAME}
- {WRITER_NAME}
Rules:
- If RESPONSE is user input, it is {REVIEWER_NAME}'s turn.
- If RESPONSE is by {REVIEWER_NAME}, it is {WRITER_NAME}'s turn.
- If RESPONSE is by {WRITER_NAME}, it is {REVIEWER_NAME}'s turn.
RESPONSE:
{{{{$lastmessage}}}}
"""
)
A funkció jelenleg nem érhető el a Javában.
A második kiértékeli, hogy mikor lépjen ki a csevegési ciklusból:
const string TerminationToken = "yes";
KernelFunction terminationFunction =
AgentGroupChat.CreatePromptFunctionForStrategy(
$$$"""
Examine the RESPONSE and determine whether the content has been deemed satisfactory.
If content is satisfactory, respond with a single word without explanation: {{{TerminationToken}}}.
If specific suggestions are being provided, it is not satisfactory.
If no correction is suggested, it is satisfactory.
RESPONSE:
{{$lastmessage}}
""",
safeParameterNames: "lastmessage");
termination_keyword = "yes"
termination_function = KernelFunctionFromPrompt(
function_name="termination",
prompt=f"""
Examine the RESPONSE and determine whether the content has been deemed satisfactory.
If the content is satisfactory, respond with a single word without explanation: {termination_keyword}.
If specific suggestions are being provided, it is not satisfactory.
If no correction is suggested, it is satisfactory.
RESPONSE:
{{{{$lastmessage}}}}
"""
)
A funkció jelenleg nem érhető el a Javában.
Mindkét stratégia csak a legutóbbi csevegőüzenet ismeretét igényli. Ez csökkenti a tokenek használatát, és javítja a teljesítményt.
ChatHistoryTruncationReducer historyReducer = new(1);
history_reducer = ChatHistoryTruncationReducer(target_count=1)
A funkció jelenleg nem érhető el a Javában.
Végül készen állunk arra, hogy mindent összehozzuk a AgentGroupChat definíciónkban.
A AgentGroupChat létrehozása a következőkből áll:
- Mindkét ügynököt vegyük bele a konstruktorba.
- Határozzon meg egy
KernelFunctionSelectionStrategya korábban definiáltKernelFunctionésKernelpéldányok használatával. - Határozzon meg egy
KernelFunctionTerminationStrategya korábban definiáltKernelFunctionésKernelpéldányok használatával.
Figyelje meg, hogy minden stratégia felelős az eredmény elemzéséért KernelFunction .
AgentGroupChat chat =
new(agentReviewer, agentWriter)
{
ExecutionSettings = new AgentGroupChatSettings
{
SelectionStrategy =
new KernelFunctionSelectionStrategy(selectionFunction, kernel)
{
// Always start with the editor agent.
InitialAgent = agentReviewer,
// Save tokens by only including the final response
HistoryReducer = historyReducer,
// The prompt variable name for the history argument.
HistoryVariableName = "lastmessage",
// Returns the entire result value as a string.
ResultParser = (result) => result.GetValue<string>() ?? agentReviewer.Name
},
TerminationStrategy =
new KernelFunctionTerminationStrategy(terminationFunction, kernel)
{
// Only evaluate for editor's response
Agents = [agentReviewer],
// Save tokens by only including the final response
HistoryReducer = historyReducer,
// The prompt variable name for the history argument.
HistoryVariableName = "lastmessage",
// Limit total number of turns
MaximumIterations = 12,
// Customer result parser to determine if the response is "yes"
ResultParser = (result) => result.GetValue<string>()?.Contains(TerminationToken, StringComparison.OrdinalIgnoreCase) ?? false
}
}
};
Console.WriteLine("Ready!");
A AgentGroupChat létrehozása a következőkből áll:
- Mindkét ügynököt vegyük bele a konstruktorba.
- Határozzon meg egy
KernelFunctionSelectionStrategya korábban definiáltKernelFunctionésKernelpéldányok használatával. - Határozzon meg egy
KernelFunctionTerminationStrategya korábban definiáltKernelFunctionésKernelpéldányok használatával.
Figyelje meg, hogy minden stratégia felelős az eredmény elemzéséért KernelFunction .
chat = AgentGroupChat(
agents=[agent_reviewer, agent_writer],
selection_strategy=KernelFunctionSelectionStrategy(
initial_agent=agent_reviewer,
function=selection_function,
kernel=kernel,
result_parser=lambda result: str(result.value[0]).strip() if result.value[0] is not None else WRITER_NAME,
history_variable_name="lastmessage",
history_reducer=history_reducer,
),
termination_strategy=KernelFunctionTerminationStrategy(
agents=[agent_reviewer],
function=termination_function,
kernel=kernel,
result_parser=lambda result: termination_keyword in str(result.value[0]).lower(),
history_variable_name="lastmessage",
maximum_iterations=10,
history_reducer=history_reducer,
),
)
A lastmessagehistory_variable_name megfelel a fent definiált KernelFunctionSelectionStrategy és KernelFunctionTerminationStrategy kérésnek. Itt helyezik el az utolsó üzenetet az előugró ablak megjelenítésekor.
A funkció jelenleg nem érhető el a Javában.
A Beszélgetés ciklus
Végre össze tudjuk hangolni a felhasználó és a AgentGroupChatközötti interakciót. Először hozzon létre egy üres hurkot.
Megjegyzés: A többi példával ellentétben nincs külső előzmény vagy szál kezelése.
AgentGroupChatbelsőleg kezeli a beszélgetési előzményeket.
bool isComplete = false;
do
{
} while (!isComplete);
is_complete: bool = False
while not is_complete:
# operational logic
A funkció jelenleg nem érhető el a Javában.
Most rögzítsük a felhasználói bemenetet az előző ciklusban. Ebben az esetben:
- Az üres bemenet figyelmen kívül lesz hagyva
- A kifejezés
EXITjelzi, hogy a beszélgetés befejeződött - A
RESETkifejezés törli aAgentGroupChatelőzményeit - Minden olyan kifejezés, amely a következővel
@kezdődik, fájlútvonalként lesz kezelve, amelynek tartalma bemenetként lesz megadva - Az érvényes bemenet a(z)
AgentGroupChat-hoz Felhasználói üzenetként hozzá lesz adva.
Console.WriteLine();
Console.Write("> ");
string input = Console.ReadLine();
if (string.IsNullOrWhiteSpace(input))
{
continue;
}
input = input.Trim();
if (input.Equals("EXIT", StringComparison.OrdinalIgnoreCase))
{
isComplete = true;
break;
}
if (input.Equals("RESET", StringComparison.OrdinalIgnoreCase))
{
await chat.ResetAsync();
Console.WriteLine("[Conversation has been reset]");
continue;
}
if (input.StartsWith("@", StringComparison.Ordinal) && input.Length > 1)
{
string filePath = input.Substring(1);
try
{
if (!File.Exists(filePath))
{
Console.WriteLine($"Unable to access file: {filePath}");
continue;
}
input = File.ReadAllText(filePath);
}
catch (Exception)
{
Console.WriteLine($"Unable to access file: {filePath}");
continue;
}
}
chat.AddChatMessage(new ChatMessageContent(AuthorRole.User, input));
Most rögzítsük a felhasználói bemenetet az előző ciklusban. Ebben az esetben:
- Az üres bemenet figyelmen kívül lesz hagyva.
- A
exitkifejezés jelzi, hogy a beszélgetés befejeződött. - A
resetkifejezés törli aAgentGroupChatelőzményeit. - A
@kezdődő kifejezések fájlútvonalként lesznek kezelve, amelynek tartalma bemenetként lesz megadva. - Az érvényes bemenet a(z)
AgentGroupChat-hoz Felhasználói üzenetként hozzá lesz adva.
A while cikluson belüli műveleti logika a következőképpen néz ki:
print()
user_input = input("User > ").strip()
if not user_input:
continue
if user_input.lower() == "exit":
is_complete = True
break
if user_input.lower() == "reset":
await chat.reset()
print("[Conversation has been reset]")
continue
# Try to grab files from the script's current directory
if user_input.startswith("@") and len(user_input) > 1:
file_name = user_input[1:]
script_dir = os.path.dirname(os.path.abspath(__file__))
file_path = os.path.join(script_dir, file_name)
try:
if not os.path.exists(file_path):
print(f"Unable to access file: {file_path}")
continue
with open(file_path, "r", encoding="utf-8") as file:
user_input = file.read()
except Exception:
print(f"Unable to access file: {file_path}")
continue
# Add the current user_input to the chat
await chat.add_chat_message(message=user_input)
A funkció jelenleg nem érhető el a Javában.
A Agent együttműködés felhasználói bemenetre adott válaszként történő elindításához és a Agent válaszok megjelenítéséhez hívja meg a AgentGroupChat; először azonban mindenképpen állítsa vissza a Befejezési állapotot bármely korábbi meghívásból.
Megjegyzés: A szolgáltatáshibákat elkapják és megjelenítik a beszélgetési ciklus összeomlásának elkerülése érdekében.
chat.IsComplete = false;
try
{
await foreach (ChatMessageContent response in chat.InvokeAsync())
{
Console.WriteLine();
Console.WriteLine($"{response.AuthorName.ToUpperInvariant()}:{Environment.NewLine}{response.Content}");
}
}
catch (HttpOperationException exception)
{
Console.WriteLine(exception.Message);
if (exception.InnerException != null)
{
Console.WriteLine(exception.InnerException.Message);
if (exception.InnerException.Data.Count > 0)
{
Console.WriteLine(JsonSerializer.Serialize(exception.InnerException.Data, new JsonSerializerOptions() { WriteIndented = true }));
}
}
}
try:
async for response in chat.invoke():
if response is None or not response.name:
continue
print()
print(f"# {response.name.upper()}:\n{response.content}")
except Exception as e:
print(f"Error during chat invocation: {e}")
# Reset the chat's complete flag for the new conversation round.
chat.is_complete = False
A funkció jelenleg nem érhető el a Javában.
Végső
Ha összehozzuk az összes lépést, megkapjuk a végleges kódot ehhez a példához. A teljes megvalósítást alább találja.
Próbálja meg használni a következő javasolt bemeneteket:
- Szia
- {"message: "helló világ"}
- {"message": "helló világ"}
- A Szemantic Kernel (SK) egy nyílt forráskódú SDK, amely lehetővé teszi a fejlesztők számára a természetes nyelvi feldolgozást (NLP) és gépi tanulási modelleket tartalmazó összetett AI-munkafolyamatok létrehozását és vezénylésére. Rugalmas platformot biztosít az olyan AI-képességek integrálásához, mint a szemantikai keresés, a szövegösszesítés és a párbeszédrendszerek az alkalmazásokba. Az SK-val egyszerűen kombinálhatja a különböző AI-szolgáltatásokat és modelleket, meghatározhatja azok kapcsolatait, és vezényelheti az interakciókat közöttük.
- alakítsd két bekezdéssé
- köszönöm
- @.\WomensSuffrage.txt
- Jó, de készen áll a főiskolai tanárom számára?
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Text.Json;
using System.Threading.Tasks;
using Azure.Identity;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Agents;
using Microsoft.SemanticKernel.Agents.Chat;
using Microsoft.SemanticKernel.Agents.History;
using Microsoft.SemanticKernel.ChatCompletion;
using Microsoft.SemanticKernel.Connectors.AzureOpenAI;
namespace AgentsSample;
public static class Program
{
public static async Task Main()
{
// Load configuration from environment variables or user secrets.
Settings settings = new();
Console.WriteLine("Creating kernel...");
IKernelBuilder builder = Kernel.CreateBuilder();
builder.AddAzureOpenAIChatCompletion(
settings.AzureOpenAI.ChatModelDeployment,
settings.AzureOpenAI.Endpoint,
new AzureCliCredential());
Kernel kernel = builder.Build();
Kernel toolKernel = kernel.Clone();
toolKernel.Plugins.AddFromType<ClipboardAccess>();
Console.WriteLine("Defining agents...");
const string ReviewerName = "Reviewer";
const string WriterName = "Writer";
ChatCompletionAgent agentReviewer =
new()
{
Name = ReviewerName,
Instructions =
"""
Your responsibility is to review and identify how to improve user provided content.
If the user has providing input or direction for content already provided, specify how to address this input.
Never directly perform the correction or provide example.
Once the content has been updated in a subsequent response, you will review the content again until satisfactory.
Always copy satisfactory content to the clipboard using available tools and inform user.
RULES:
- Only identify suggestions that are specific and actionable.
- Verify previous suggestions have been addressed.
- Never repeat previous suggestions.
""",
Kernel = toolKernel,
Arguments = new KernelArguments(new AzureOpenAIPromptExecutionSettings() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() })
};
ChatCompletionAgent agentWriter =
new()
{
Name = WriterName,
Instructions =
"""
Your sole responsibility is to rewrite content according to review suggestions.
- Always apply all review direction.
- Always revise the content in its entirety without explanation.
- Never address the user.
""",
Kernel = kernel,
};
KernelFunction selectionFunction =
AgentGroupChat.CreatePromptFunctionForStrategy(
$$$"""
Examine the provided RESPONSE and choose the next participant.
State only the name of the chosen participant without explanation.
Never choose the participant named in the RESPONSE.
Choose only from these participants:
- {{{ReviewerName}}}
- {{{WriterName}}}
Always follow these rules when choosing the next participant:
- If RESPONSE is user input, it is {{{ReviewerName}}}'s turn.
- If RESPONSE is by {{{ReviewerName}}}, it is {{{WriterName}}}'s turn.
- If RESPONSE is by {{{WriterName}}}, it is {{{ReviewerName}}}'s turn.
RESPONSE:
{{$lastmessage}}
""",
safeParameterNames: "lastmessage");
const string TerminationToken = "yes";
KernelFunction terminationFunction =
AgentGroupChat.CreatePromptFunctionForStrategy(
$$$"""
Examine the RESPONSE and determine whether the content has been deemed satisfactory.
If content is satisfactory, respond with a single word without explanation: {{{TerminationToken}}}.
If specific suggestions are being provided, it is not satisfactory.
If no correction is suggested, it is satisfactory.
RESPONSE:
{{$lastmessage}}
""",
safeParameterNames: "lastmessage");
ChatHistoryTruncationReducer historyReducer = new(1);
AgentGroupChat chat =
new(agentReviewer, agentWriter)
{
ExecutionSettings = new AgentGroupChatSettings
{
SelectionStrategy =
new KernelFunctionSelectionStrategy(selectionFunction, kernel)
{
// Always start with the editor agent.
InitialAgent = agentReviewer,
// Save tokens by only including the final response
HistoryReducer = historyReducer,
// The prompt variable name for the history argument.
HistoryVariableName = "lastmessage",
// Returns the entire result value as a string.
ResultParser = (result) => result.GetValue<string>() ?? agentReviewer.Name
},
TerminationStrategy =
new KernelFunctionTerminationStrategy(terminationFunction, kernel)
{
// Only evaluate for editor's response
Agents = [agentReviewer],
// Save tokens by only including the final response
HistoryReducer = historyReducer,
// The prompt variable name for the history argument.
HistoryVariableName = "lastmessage",
// Limit total number of turns
MaximumIterations = 12,
// Customer result parser to determine if the response is "yes"
ResultParser = (result) => result.GetValue<string>()?.Contains(TerminationToken, StringComparison.OrdinalIgnoreCase) ?? false
}
}
};
Console.WriteLine("Ready!");
bool isComplete = false;
do
{
Console.WriteLine();
Console.Write("> ");
string input = Console.ReadLine();
if (string.IsNullOrWhiteSpace(input))
{
continue;
}
input = input.Trim();
if (input.Equals("EXIT", StringComparison.OrdinalIgnoreCase))
{
isComplete = true;
break;
}
if (input.Equals("RESET", StringComparison.OrdinalIgnoreCase))
{
await chat.ResetAsync();
Console.WriteLine("[Conversation has been reset]");
continue;
}
if (input.StartsWith("@", StringComparison.Ordinal) && input.Length > 1)
{
string filePath = input.Substring(1);
try
{
if (!File.Exists(filePath))
{
Console.WriteLine($"Unable to access file: {filePath}");
continue;
}
input = File.ReadAllText(filePath);
}
catch (Exception)
{
Console.WriteLine($"Unable to access file: {filePath}");
continue;
}
}
chat.AddChatMessage(new ChatMessageContent(AuthorRole.User, input));
chat.IsComplete = false;
try
{
await foreach (ChatMessageContent response in chat.InvokeAsync())
{
Console.WriteLine();
Console.WriteLine($"{response.AuthorName.ToUpperInvariant()}:{Environment.NewLine}{response.Content}");
}
}
catch (HttpOperationException exception)
{
Console.WriteLine(exception.Message);
if (exception.InnerException != null)
{
Console.WriteLine(exception.InnerException.Message);
if (exception.InnerException.Data.Count > 0)
{
Console.WriteLine(JsonSerializer.Serialize(exception.InnerException.Data, new JsonSerializerOptions() { WriteIndented = true }));
}
}
}
} while (!isComplete);
}
private sealed class ClipboardAccess
{
[KernelFunction]
[Description("Copies the provided content to the clipboard.")]
public static void SetClipboard(string content)
{
if (string.IsNullOrWhiteSpace(content))
{
return;
}
using Process clipProcess = Process.Start(
new ProcessStartInfo
{
FileName = "clip",
RedirectStandardInput = true,
UseShellExecute = false,
});
clipProcess.StandardInput.Write(content);
clipProcess.StandardInput.Close();
}
}
}
Az összes lépést összehozva most már megvan a példa végleges kódja. A teljes megvalósítás alább látható.
A javasolt bemenetek egyikével próbálkozhat. Az ügynök csevegésének kezdetekor az ügynökök több iterációra cserélik az üzeneteket, amíg a véleményező ügynök meg nem elégedett a szövegíró munkájával. A while hurok biztosítja, hogy a beszélgetés folytatódjon, még akkor is, ha a csevegés kezdetben befejezettnek tekinthető, a is_complete jelzőt False-re állítva vissza.
- Rozes piros, lila kék.
- A Szemantic Kernel (SK) egy nyílt forráskódú SDK, amely lehetővé teszi a fejlesztők számára a természetes nyelvi feldolgozást (NLP) és gépi tanulási modelleket tartalmazó összetett AI-munkafolyamatok létrehozását és vezénylésére. Rugalmas platformot biztosít az olyan AI-képességek integrálásához, mint a szemantikai keresés, a szövegösszesítés és a párbeszédrendszerek az alkalmazásokba. Az SK-val egyszerűen kombinálhatja a különböző AI-szolgáltatásokat és modelleket, meghatározhatja azok kapcsolatait, és vezényelheti az interakciókat közöttük.
- Tedd ezt két bekezdéssé
- köszönöm
- @WomensSuffrage.txt
- Jó, de megfelel a főiskolai professzorom elvárásainak?
Jótanács
Bármely fájlra hivatkozhat a @<file_path_to_file>megadásával. Ha a fent említett "WomensSuffrage" szövegre szeretne hivatkozni, töltse le innen, és helyezze az aktuális munka könyvtárába. Ezután hivatkozhat rá a(z) @WomensSuffrage.txt-ként.
import asyncio
import os
from semantic_kernel import Kernel
from semantic_kernel.agents import AgentGroupChat, ChatCompletionAgent
from semantic_kernel.agents.strategies import (
KernelFunctionSelectionStrategy,
KernelFunctionTerminationStrategy,
)
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion
from semantic_kernel.contents import ChatHistoryTruncationReducer
from semantic_kernel.functions import KernelFunctionFromPrompt
"""
The following sample demonstrates how to create a simple,
agent group chat that utilizes a Reviewer Chat Completion
Agent along with a Writer Chat Completion Agent to
complete a user's task.
"""
# Define agent names
REVIEWER_NAME = "Reviewer"
WRITER_NAME = "Writer"
def create_kernel() -> Kernel:
"""Creates a Kernel instance with an Azure OpenAI ChatCompletion service."""
kernel = Kernel()
kernel.add_service(service=AzureChatCompletion())
return kernel
async def main():
# Create a single kernel instance for all agents.
kernel = create_kernel()
# Create ChatCompletionAgents using the same kernel.
agent_reviewer = ChatCompletionAgent(
kernel=kernel,
name=REVIEWER_NAME,
instructions="""
Your responsibility is to review and identify how to improve user provided content.
If the user has provided input or direction for content already provided, specify how to address this input.
Never directly perform the correction or provide an example.
Once the content has been updated in a subsequent response, review it again until it is satisfactory.
RULES:
- Only identify suggestions that are specific and actionable.
- Verify previous suggestions have been addressed.
- Never repeat previous suggestions.
""",
)
agent_writer = ChatCompletionAgent(
kernel=kernel,
name=WRITER_NAME,
instructions="""
Your sole responsibility is to rewrite content according to review suggestions.
- Always apply all review directions.
- Always revise the content in its entirety without explanation.
- Never address the user.
""",
)
# Define a selection function to determine which agent should take the next turn.
selection_function = KernelFunctionFromPrompt(
function_name="selection",
prompt=f"""
Examine the provided RESPONSE and choose the next participant.
State only the name of the chosen participant without explanation.
Never choose the participant named in the RESPONSE.
Choose only from these participants:
- {REVIEWER_NAME}
- {WRITER_NAME}
Rules:
- If RESPONSE is user input, it is {REVIEWER_NAME}'s turn.
- If RESPONSE is by {REVIEWER_NAME}, it is {WRITER_NAME}'s turn.
- If RESPONSE is by {WRITER_NAME}, it is {REVIEWER_NAME}'s turn.
RESPONSE:
{{{{$lastmessage}}}}
""",
)
# Define a termination function where the reviewer signals completion with "yes".
termination_keyword = "yes"
termination_function = KernelFunctionFromPrompt(
function_name="termination",
prompt=f"""
Examine the RESPONSE and determine whether the content has been deemed satisfactory.
If the content is satisfactory, respond with a single word without explanation: {termination_keyword}.
If specific suggestions are being provided, it is not satisfactory.
If no correction is suggested, it is satisfactory.
RESPONSE:
{{{{$lastmessage}}}}
""",
)
history_reducer = ChatHistoryTruncationReducer(target_count=5)
# Create the AgentGroupChat with selection and termination strategies.
chat = AgentGroupChat(
agents=[agent_reviewer, agent_writer],
selection_strategy=KernelFunctionSelectionStrategy(
initial_agent=agent_reviewer,
function=selection_function,
kernel=kernel,
result_parser=lambda result: str(result.value[0]).strip() if result.value[0] is not None else WRITER_NAME,
history_variable_name="lastmessage",
history_reducer=history_reducer,
),
termination_strategy=KernelFunctionTerminationStrategy(
agents=[agent_reviewer],
function=termination_function,
kernel=kernel,
result_parser=lambda result: termination_keyword in str(result.value[0]).lower(),
history_variable_name="lastmessage",
maximum_iterations=10,
history_reducer=history_reducer,
),
)
print(
"Ready! Type your input, or 'exit' to quit, 'reset' to restart the conversation. "
"You may pass in a file path using @<path_to_file>."
)
is_complete = False
while not is_complete:
print()
user_input = input("User > ").strip()
if not user_input:
continue
if user_input.lower() == "exit":
is_complete = True
break
if user_input.lower() == "reset":
await chat.reset()
print("[Conversation has been reset]")
continue
# Try to grab files from the script's current directory
if user_input.startswith("@") and len(user_input) > 1:
file_name = user_input[1:]
script_dir = os.path.dirname(os.path.abspath(__file__))
file_path = os.path.join(script_dir, file_name)
try:
if not os.path.exists(file_path):
print(f"Unable to access file: {file_path}")
continue
with open(file_path, "r", encoding="utf-8") as file:
user_input = file.read()
except Exception:
print(f"Unable to access file: {file_path}")
continue
# Add the current user_input to the chat
await chat.add_chat_message(message=user_input)
try:
async for response in chat.invoke():
if response is None or not response.name:
continue
print()
print(f"# {response.name.upper()}:\n{response.content}")
except Exception as e:
print(f"Error during chat invocation: {e}")
# Reset the chat's complete flag for the new conversation round.
chat.is_complete = False
if __name__ == "__main__":
asyncio.run(main())
A teljes kóda fent látható módon az adattárunkban található.
A funkció jelenleg nem érhető el a Javában.