Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Microsoft Agent Framework, sınıfından AIAgent devralarak ve gerekli yöntemleri uygulayarak özel aracılar oluşturulmasını destekler.
Bu makale, kullanıcı girişini büyük harfle tekrar eden basit bir özelleştirilmiş ajan nasıl oluşturulacağını gösterir. Çoğu durumda kendi aracınızı oluşturmak için yapay zeka hizmetiyle daha karmaşık mantık ve tümleştirme gerekir.
Başlangıç Yapmak
Projenize gerekli NuGet paketlerini ekleyin.
dotnet add package Microsoft.Agents.AI.Abstractions --prerelease
Özel Aracı Oluşturma
Ajan İş Parçacığı
Özel bir temsilci oluşturmak için, ileti geçmişi ve temsilcinin sürdürmesi gereken diğer tüm durumlar dahil olmak üzere, tek bir konuşmanın durumunu izlemek için kullanılan bir iş parçacığına da ihtiyacınız vardır.
Başlamayı kolaylaştırmak için, yaygın iş parçacığı depolama mekanizmalarını uygulayan çeşitli temel sınıflardan devir alabilirsiniz.
-
InMemoryAgentThread- sohbet geçmişini bellekte depolar ve JSON'a seri hale getirilebilir. -
ServiceIdAgentThread- herhangi bir sohbet geçmişi depolamaz, ancak bir kimliği sohbet geçmişinin harici olarak depolanabileceği yazışmayla ilişkilendirmenize olanak tanır.
Bu örnekte, özel iş parçacığı için temel sınıf olarak InMemoryAgentThread öğesini kullanacaksınız.
internal sealed class CustomAgentThread : InMemoryAgentThread
{
internal CustomAgentThread() : base() { }
internal CustomAgentThread(JsonElement serializedThreadState, JsonSerializerOptions? jsonSerializerOptions = null)
: base(serializedThreadState, jsonSerializerOptions) { }
}
Agent sınıfı
Ardından, AIAgent sınıfından türeterek aracı sınıfının kendisini oluşturun.
internal sealed class UpperCaseParrotAgent : AIAgent
{
}
Konuları oluşturma
İş parçacıkları her zaman aracı sınıfındaki iki fabrika yöntemiyle oluşturulur. Bu, aracının iş parçacıklarının nasıl oluşturulduğunu ve seri durumdan çıkarıldığını denetlemesine olanak tanır. Bu nedenle aracılar, oluşturulduğunda iş parçacığına gereken ek durumları veya davranışları ekleyebilir.
İki yöntemin uygulanması gerekir:
public override AgentThread GetNewThread() => new CustomAgentThread();
public override AgentThread DeserializeThread(JsonElement serializedThread, JsonSerializerOptions? jsonSerializerOptions = null)
=> new CustomAgentThread(serializedThread, jsonSerializerOptions);
Temel ajan mantığı
Aracının temel mantığı, tüm giriş iletilerini almak, metinlerini büyük harfe dönüştürmek ve bunları yanıt iletileri olarak döndürmektir.
Bu mantığı içerecek şekilde aşağıdaki yöntemi ekleyin.
Giriş iletilerinin çeşitli yönlerinin geçerli yanıt iletileri olması için değiştirilmesi gerektiğinden, giriş iletileri kopyalanır. Örneğin, rolün Assistant olarak değiştirilmesi gerekir.
private static IEnumerable<ChatMessage> CloneAndToUpperCase(IEnumerable<ChatMessage> messages, string agentName) => messages.Select(x =>
{
var messageClone = x.Clone();
messageClone.Role = ChatRole.Assistant;
messageClone.MessageId = Guid.NewGuid().ToString();
messageClone.AuthorName = agentName;
messageClone.Contents = x.Contents.Select(c => c is TextContent tc ? new TextContent(tc.Text.ToUpperInvariant())
{
AdditionalProperties = tc.AdditionalProperties,
Annotations = tc.Annotations,
RawRepresentation = tc.RawRepresentation
} : c).ToList();
return messageClone;
});
Aracı çalıştırma yöntemleri
Son olarak, aracıyı çalıştırmak için kullanılan iki temel yöntemi uygulamanız gerekir: biri akış dışı ve biri akış için.
Her iki yöntem için de bir iş parçacığının sağlandığından emin olmanız ve sağlanmadıysa yeni bir iş parçacığı oluşturmanız gerekir.
Ardından iş parçacığı, NotifyThreadOfNewMessagesAsync çağrılarak yeni iletilerle güncellenebilir.
Bunu yapmazsanız, kullanıcı aracıyla çoklu tur konuşması yapamaz ve her oturum yeni bir etkileşim olacaktır.
public override async Task<AgentRunResponse> RunAsync(IEnumerable<ChatMessage> messages, AgentThread? thread = null, AgentRunOptions? options = null, CancellationToken cancellationToken = default)
{
thread ??= this.GetNewThread();
List<ChatMessage> responseMessages = CloneAndToUpperCase(messages, this.DisplayName).ToList();
await NotifyThreadOfNewMessagesAsync(thread, messages.Concat(responseMessages), cancellationToken);
return new AgentRunResponse
{
AgentId = this.Id,
ResponseId = Guid.NewGuid().ToString(),
Messages = responseMessages
};
}
public override async IAsyncEnumerable<AgentRunResponseUpdate> RunStreamingAsync(IEnumerable<ChatMessage> messages, AgentThread? thread = null, AgentRunOptions? options = null, [EnumeratorCancellation] CancellationToken cancellationToken = default)
{
thread ??= this.GetNewThread();
List<ChatMessage> responseMessages = CloneAndToUpperCase(messages, this.DisplayName).ToList();
await NotifyThreadOfNewMessagesAsync(thread, messages.Concat(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()
};
}
}
Ajanı Kullanma
Yöntemlerin AIAgent tümü doğru uygulanırsa, aracı standart bir AIAgent olur ve standart aracı işlemlerini destekler.
Aracıları çalıştırma ve aracılarla etkileşim kurma hakkında daha fazla bilgi için bkz. Aracı kullanmaya başlama öğreticileri.
Microsoft Agent Framework, sınıfından BaseAgent devralarak ve gerekli yöntemleri uygulayarak özel aracılar oluşturulmasını destekler.
Bu belgede, ön ek ile kullanıcı girişini geri döndüren basit bir özel aracı oluşturma gösterilmektedir. Çoğu durumda kendi aracınızı oluşturmak için yapay zeka hizmetiyle daha karmaşık mantık ve tümleştirme gerekir.
Başlangıç Yapmak
Projenize gerekli Python paketlerini ekleyin.
pip install agent-framework-core --pre
Özelleştirilmiş Temsilci Oluşturma
Aracı Protokolü
Çerçeve, tüm aracıların AgentProtocol uygulaması gereken arabirimi tanımlayan protokolü sağlar. Özel aracılar bu protokolü doğrudan uygulayabilir veya kolaylık sağlamak için sınıfını BaseAgent genişletebilir.
from agent_framework import AgentProtocol, AgentRunResponse, AgentRunResponseUpdate, AgentThread, ChatMessage
from collections.abc import AsyncIterable
from typing import Any
class MyCustomAgent(AgentProtocol):
"""A custom agent that implements the AgentProtocol directly."""
@property
def id(self) -> str:
"""Returns the ID of the agent."""
...
async def run(
self,
messages: str | ChatMessage | list[str] | list[ChatMessage] | None = None,
*,
thread: AgentThread | None = None,
**kwargs: Any,
) -> AgentRunResponse:
"""Execute the agent and return a complete response."""
...
def run_stream(
self,
messages: str | ChatMessage | list[str] | list[ChatMessage] | None = None,
*,
thread: AgentThread | None = None,
**kwargs: Any,
) -> AsyncIterable[AgentRunResponseUpdate]:
"""Execute the agent and yield streaming response updates."""
...
BaseAgent kullanma
Önerilen yaklaşım, ortak işlevsellik sağlayan ve uygulamayı basitleştiren sınıfını genişletmektir BaseAgent :
from agent_framework import (
BaseAgent,
AgentRunResponse,
AgentRunResponseUpdate,
AgentThread,
ChatMessage,
Role,
TextContent,
)
from collections.abc import AsyncIterable
from typing import Any
class EchoAgent(BaseAgent):
"""A simple custom agent that echoes user messages with a prefix."""
echo_prefix: str = "Echo: "
def __init__(
self,
*,
name: str | None = None,
description: str | None = None,
echo_prefix: str = "Echo: ",
**kwargs: Any,
) -> None:
"""Initialize the EchoAgent.
Args:
name: The name of the agent.
description: The description of the agent.
echo_prefix: The prefix to add to echoed messages.
**kwargs: Additional keyword arguments passed to BaseAgent.
"""
super().__init__(
name=name,
description=description,
echo_prefix=echo_prefix,
**kwargs,
)
async def run(
self,
messages: str | ChatMessage | list[str] | list[ChatMessage] | None = None,
*,
thread: AgentThread | None = None,
**kwargs: Any,
) -> AgentRunResponse:
"""Execute the agent and return a complete response.
Args:
messages: The message(s) to process.
thread: The conversation thread (optional).
**kwargs: Additional keyword arguments.
Returns:
An AgentRunResponse containing the agent's reply.
"""
# Normalize input messages to a list
normalized_messages = self._normalize_messages(messages)
if not normalized_messages:
response_message = ChatMessage(
role=Role.ASSISTANT,
contents=[TextContent(text="Hello! I'm a custom echo agent. Send me a message and I'll echo it back.")],
)
else:
# For simplicity, echo the last user message
last_message = normalized_messages[-1]
if last_message.text:
echo_text = f"{self.echo_prefix}{last_message.text}"
else:
echo_text = f"{self.echo_prefix}[Non-text message received]"
response_message = ChatMessage(role=Role.ASSISTANT, contents=[TextContent(text=echo_text)])
# Notify the thread of new messages if provided
if thread is not None:
await self._notify_thread_of_new_messages(thread, normalized_messages, response_message)
return AgentRunResponse(messages=[response_message])
async def run_stream(
self,
messages: str | ChatMessage | list[str] | list[ChatMessage] | None = None,
*,
thread: AgentThread | None = None,
**kwargs: Any,
) -> AsyncIterable[AgentRunResponseUpdate]:
"""Execute the agent and yield streaming response updates.
Args:
messages: The message(s) to process.
thread: The conversation thread (optional).
**kwargs: Additional keyword arguments.
Yields:
AgentRunResponseUpdate objects containing chunks of the response.
"""
# Normalize input messages to a list
normalized_messages = self._normalize_messages(messages)
if not normalized_messages:
response_text = "Hello! I'm a custom echo agent. Send me a message and I'll echo it back."
else:
# For simplicity, echo the last user message
last_message = normalized_messages[-1]
if last_message.text:
response_text = f"{self.echo_prefix}{last_message.text}"
else:
response_text = f"{self.echo_prefix}[Non-text message received]"
# Simulate streaming by yielding the response word by word
words = response_text.split()
for i, word in enumerate(words):
# Add space before word except for the first one
chunk_text = f" {word}" if i > 0 else word
yield AgentRunResponseUpdate(
contents=[TextContent(text=chunk_text)],
role=Role.ASSISTANT,
)
# Small delay to simulate streaming
await asyncio.sleep(0.1)
# Notify the thread of the complete response if provided
if thread is not None:
complete_response = ChatMessage(role=Role.ASSISTANT, contents=[TextContent(text=response_text)])
await self._notify_thread_of_new_messages(thread, normalized_messages, complete_response)
Ajanı Kullanma
Aracı yöntemlerinin tümü doğru şekilde uygulanırsa, ajan tüm standart ajan işlevlerini destekler.
Aracıları çalıştırma ve aracılarla etkileşim kurma hakkında daha fazla bilgi için bkz. Aracı kullanmaya başlama öğreticileri.