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.
Bu öğretici, bir AIContextProvider uygulayarak ve bunu aracıya ekleyerek bir aracıya nasıl bellek ekleyeceğinizi göstermektedir.
Önemli
Tüm aracı türleri AIContextProvider desteklemez. Bu adım, bir ChatClientAgent kullanır; bu da AIContextProvider'yi destekler.
Önkoşullar
Önkoşullar ve NuGet paketlerini yükleme için bu öğreticideki Basit bir aracı oluşturma ve çalıştırma adımına bakın.
AIContextProvider oluştur##
AIContextProvider, devralabileceğiniz ve bir AgentThread için bir ChatClientAgent ile ilişkilendirilebilen soyut bir sınıftır.
Şunları yapmanızı sağlar:
- Aracı temel çıkarım hizmetini çağırmadan önce ve sonra özel mantık çalıştırın.
- Aracı, temel alınan çıkarım hizmetini çağırmadan önce ek bağlam sağlayın.
- Aracıya sağlanan ve aracı tarafından oluşturulan tüm iletileri inceleyin.
Çağrı öncesi ve sonrası olayları
sınıfı, AIContextProvider aracı temel çıkarım hizmetini çağırmadan önce ve sonra özel mantık çalıştırmak için geçersiz kılabileceğiniz iki yönteme sahiptir:
-
InvokingAsync- temel çıkarım hizmeti devreye girmeden önce çağrılır. BirAIContextnesne döndürerek aracıya ek bağlam sağlayabilirsiniz. Bu bağlam, temel alınan hizmeti çağırmadan önce aracının mevcut bağlamıyla birleştirilir. İsteğe eklemek için yönergeler, araçlar ve iletiler sağlamak mümkündür. -
InvokedAsync- aracı temel alınan çıkarım hizmetinden bir yanıt aldıktan sonra çağrılır. İstek ve yanıt iletilerini inceleyebilir ve bağlam sağlayıcısının durumunu güncelleştirebilirsiniz.
Serialization
AIContextProvider örnekleri, iş parçacığı oluşturulduğunda ve serileştirilmiş bir durumdan iş parçacığı devam ettirildiğinde AgentThread öğesine eklenir.
AIContextProvider örneği, ajanın çağrıları arasında kalıcı olması gereken kendi durumuna sahip olabilir. Örneğin, kullanıcı hakkındaki bilgileri hatırlayan bir bellek bileşeni, durumunun bir parçası olarak belleklere sahip olabilir.
Kalıcı iş parçacıklarına izin vermek için SerializeAsync sınıfının AIContextProvider yöntemini uygulamanız gerekir. Ayrıca, bir iş parçacığını devam ettirirken durumu seri durumdan çıkarmak için kullanılabilecek bir JsonElement parametre alan bir oluşturucu sağlamanız gerekir.
Örnek AIContextProvider uygulaması
Aşağıdaki özel bellek bileşeni örneği, kullanıcının adını ve yaşını anımsar ve her çağrıdan önce aracıya sağlar.
İlk olarak, bellekleri tutmak için bir model sınıfı oluşturun.
internal sealed class UserInfo
{
public string? UserName { get; set; }
public int? UserAge { get; set; }
}
Ardından bellekleri yönetmek için AIContextProvider uygulayabilirsiniz.
Aşağıdaki UserInfoMemory sınıf aşağıdaki davranışı içerir:
- Her çalıştırmanın sonunda iş parçacığına yeni mesajlar eklendiğinde, kullanıcı mesajlarında kullanıcının adını ve yaşını aramak için bir
IChatClientkullanılır. - Her çağrıdan önce aracıya mevcut bellekleri sağlar.
- Kullanılabilir bellek yoksa, aracıya eksik bilgileri kullanıcıya sormasını ve bilgiler sağlanana kadar hiçbir soruyu yanıtlamamasını ister.
- Ayrıca iş parçacığı durumunun bir parçası olarak belleklerin kalıcı hale getirilmesine izin vermek için serileştirme uygular.
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
internal sealed class UserInfoMemory : AIContextProvider
{
private readonly IChatClient _chatClient;
public UserInfoMemory(IChatClient chatClient, UserInfo? userInfo = null)
{
this._chatClient = chatClient;
this.UserInfo = userInfo ?? new UserInfo();
}
public UserInfoMemory(IChatClient chatClient, JsonElement serializedState, JsonSerializerOptions? jsonSerializerOptions = null)
{
this._chatClient = chatClient;
this.UserInfo = serializedState.ValueKind == JsonValueKind.Object ?
serializedState.Deserialize<UserInfo>(jsonSerializerOptions)! :
new UserInfo();
}
public UserInfo UserInfo { get; set; }
public override async ValueTask InvokedAsync(
InvokedContext context,
CancellationToken cancellationToken = default)
{
if ((this.UserInfo.UserName is null || this.UserInfo.UserAge is null) && context.RequestMessages.Any(x => x.Role == ChatRole.User))
{
var result = await this._chatClient.GetResponseAsync<UserInfo>(
context.RequestMessages,
new ChatOptions()
{
Instructions = "Extract the user's name and age from the message if present. If not present return nulls."
},
cancellationToken: cancellationToken);
this.UserInfo.UserName ??= result.Result.UserName;
this.UserInfo.UserAge ??= result.Result.UserAge;
}
}
public override ValueTask<AIContext> InvokingAsync(
InvokingContext context,
CancellationToken cancellationToken = default)
{
StringBuilder instructions = new();
instructions
.AppendLine(
this.UserInfo.UserName is null ?
"Ask the user for their name and politely decline to answer any questions until they provide it." :
$"The user's name is {this.UserInfo.UserName}.")
.AppendLine(
this.UserInfo.UserAge is null ?
"Ask the user for their age and politely decline to answer any questions until they provide it." :
$"The user's age is {this.UserInfo.UserAge}.");
return new ValueTask<AIContext>(new AIContext
{
Instructions = instructions.ToString()
});
}
public override JsonElement Serialize(JsonSerializerOptions? jsonSerializerOptions = null)
{
return JsonSerializer.SerializeToElement(this.UserInfo, jsonSerializerOptions);
}
}
AIContextProvider'i bir aracıyla kullanma
Özel AIContextProviderkullanmak için aracıyı oluştururken bir AIContextProviderFactory sağlamanız gerekir. Bu fabrika, temsilcinin her iş parçacığı için istenen AIContextProvider yeni bir örneğini oluşturmasına olanak tanır.
ChatClientAgent oluştururken, diğer tüm aracı seçeneklerinin yanı sıra ChatClientAgentOptions sağlamanıza olanak tanıyan bir AIContextProviderFactory nesnesi sağlamak mümkündür.
using System;
using Azure.AI.OpenAI;
using Azure.Identity;
using OpenAI.Chat;
using OpenAI;
ChatClient chatClient = new AzureOpenAIClient(
new Uri("https://<myresource>.openai.azure.com"),
new AzureCliCredential())
.GetChatClient("gpt-4o-mini");
AIAgent agent = chatClient.CreateAIAgent(new ChatClientAgentOptions()
{
ChatOptions = new() { Instructions = "You are a friendly assistant. Always address the user by their name." },
AIContextProviderFactory = ctx => new UserInfoMemory(
chatClient.AsIChatClient(),
ctx.SerializedState,
ctx.JsonSerializerOptions)
});
Yeni bir iş parçacığı oluşturulduğunda, AIContextProviderGetNewThread tarafından oluşturulup iş parçacığına eklenir. Bellekler ayıklandıktan sonra, iş parçacığının GetService yöntemi aracılığıyla bellek bileşenine erişmek ve bellekleri incelemek mümkündür.
// Create a new thread for the conversation.
AgentThread thread = agent.GetNewThread();
Console.WriteLine(await agent.RunAsync("Hello, what is the square root of 9?", thread));
Console.WriteLine(await agent.RunAsync("My name is Ruaidhrí", thread));
Console.WriteLine(await agent.RunAsync("I am 20 years old", thread));
// Access the memory component via the thread's GetService method.
var userInfo = thread.GetService<UserInfoMemory>()?.UserInfo;
Console.WriteLine($"MEMORY - User Name: {userInfo?.UserName}");
Console.WriteLine($"MEMORY - User Age: {userInfo?.UserAge}");
Bu öğreticide, bir ContextProvider uygulayarak ve bunu aracıya ekleyerek aracının belleğini nasıl artıracağınız gösterilmektedir.
Önemli
Tüm aracı türleri ContextProvider desteklemez. Bu adım, bir ChatAgent kullanır; bu da ContextProvider'yi destekler.
Önkoşullar
Önkoşullar ve paketleri yükleme için bu öğreticideki Basit bir aracı oluşturma ve çalıştırma adımına bakın.
Bir ContextProvider oluşturma
ContextProvider öğesinden devralabileceğiniz ve bir AgentThread için ChatAgent ile ilişkilendirebileceğiniz soyut bir sınıftır.
Şunları yapmanızı sağlar:
- Ajan temel çıkarım hizmetini çağırmadan önce ve sonra özel mantığı çalıştırın.
- Çıkarım hizmetini çağırmadan önce ajan için ek bağlam sağlayın.
- Aracıya sağlanan ve aracı tarafından oluşturulan tüm iletileri inceleyin.
Çağrı öncesi ve sonrası olayları
sınıfı, ContextProvider aracı temel çıkarım hizmetini çağırmadan önce ve sonra özel mantık çalıştırmak için geçersiz kılabileceğiniz iki yönteme sahiptir:
-
invoking- temel çıkarım hizmeti devreye girmeden önce çağrılır. BirContextnesne döndürerek aracıya ek bağlam sağlayabilirsiniz. Bu bağlam, temel alınan hizmeti çağırmadan önce aracının mevcut bağlamıyla birleştirilir. İsteğe eklemek için yönergeler, araçlar ve iletiler sağlamak mümkündür. -
invoked- aracı temel alınan çıkarım hizmetinden bir yanıt aldıktan sonra çağrılır. İstek ve yanıt iletilerini inceleyebilir ve bağlam sağlayıcısının durumunu güncelleştirebilirsiniz.
Serialization
ContextProvider örnekleri, iş parçacığı oluşturulduğunda ve serileştirilmiş bir durumdan iş parçacığı devam ettirildiğinde AgentThread öğesine eklenir.
ContextProvider örneği, ajanın çağrıları arasında kalıcı olması gereken kendi durumuna sahip olabilir. Örneğin, kullanıcı hakkındaki bilgileri hatırlayan bir bellek bileşeni, durumunun bir parçası olarak belleklere sahip olabilir.
Kalıcı iş parçacıklarına izin vermek için ContextProvider sınıfında serileştirmeyi uygulamanız gerekir. Ayrıca, bir iş parçacığını devam ettirirken serileştirilmiş verilerden durumu geri yükleyebilen bir oluşturucu sağlamanız gerekir.
Örnek ContextProvider uygulaması
Aşağıdaki özel bellek bileşeni örneği, kullanıcının adını ve yaşını anımsar ve her çağrıdan önce aracıya sağlar.
İlk olarak, bellekleri tutmak için bir model sınıfı oluşturun.
from pydantic import BaseModel
class UserInfo(BaseModel):
name: str | None = None
age: int | None = None
Ardından bellekleri yönetmek için ContextProvider uygulayabilirsiniz.
Aşağıdaki UserInfoMemory sınıf aşağıdaki davranışı içerir:
- Her çalıştırmanın sonunda iş parçacığına yeni iletiler eklendiğinde kullanıcı iletilerinde kullanıcının adını ve yaşını aramak için bir sohbet istemcisi kullanır.
- Her çağrıdan önce aracıya mevcut bellekleri sağlar.
- Kullanılabilir bellek yoksa, aracıya eksik bilgileri kullanıcıya sormasını ve bilgiler sağlanana kadar hiçbir soruyu yanıtlamamasını ister.
- Ayrıca iş parçacığı durumunun bir parçası olarak belleklerin kalıcı hale getirilmesine izin vermek için serileştirme uygular.
from collections.abc import MutableSequence, Sequence
from typing import Any
from agent_framework import ContextProvider, Context, ChatAgent, ChatClientProtocol, ChatMessage, ChatOptions
class UserInfoMemory(ContextProvider):
def __init__(self, chat_client: ChatClientProtocol, user_info: UserInfo | None = None, **kwargs: Any):
"""Create the memory.
If you pass in kwargs, they will be attempted to be used to create a UserInfo object.
"""
self._chat_client = chat_client
if user_info:
self.user_info = user_info
elif kwargs:
self.user_info = UserInfo.model_validate(kwargs)
else:
self.user_info = UserInfo()
async def invoked(
self,
request_messages: ChatMessage | Sequence[ChatMessage],
response_messages: ChatMessage | Sequence[ChatMessage] | None = None,
invoke_exception: Exception | None = None,
**kwargs: Any,
) -> None:
"""Extract user information from messages after each agent call."""
# Ensure request_messages is a list
messages_list = [request_messages] if isinstance(request_messages, ChatMessage) else list(request_messages)
# Check if we need to extract user info from user messages
user_messages = [msg for msg in messages_list if msg.role.value == "user"]
if (self.user_info.name is None or self.user_info.age is None) and user_messages:
try:
# Use the chat client to extract structured information
result = await self._chat_client.get_response(
messages=messages_list,
chat_options=ChatOptions(
instructions=(
"Extract the user's name and age from the message if present. "
"If not present return nulls."
),
response_format=UserInfo,
),
)
# Update user info with extracted data
if result.value and isinstance(result.value, UserInfo):
if self.user_info.name is None and result.value.name:
self.user_info.name = result.value.name
if self.user_info.age is None and result.value.age:
self.user_info.age = result.value.age
except Exception:
pass # Failed to extract, continue without updating
async def invoking(self, messages: ChatMessage | MutableSequence[ChatMessage], **kwargs: Any) -> Context:
"""Provide user information context before each agent call."""
instructions: list[str] = []
if self.user_info.name is None:
instructions.append(
"Ask the user for their name and politely decline to answer any questions until they provide it."
)
else:
instructions.append(f"The user's name is {self.user_info.name}.")
if self.user_info.age is None:
instructions.append(
"Ask the user for their age and politely decline to answer any questions until they provide it."
)
else:
instructions.append(f"The user's age is {self.user_info.age}.")
# Return context with additional instructions
return Context(instructions=" ".join(instructions))
def serialize(self) -> str:
"""Serialize the user info for thread persistence."""
return self.user_info.model_dump_json()
ContextProvider'i bir aracıyla kullanma
Özel ContextProvider kullanmak için, aracıyı oluştururken örneklenmiş ContextProvider sağlamanız gerekir.
ChatAgent oluştururken, bellek bileşenini aracıya eklemek için context_providers parametresini sağlayabilirsiniz.
import asyncio
from agent_framework import ChatAgent
from agent_framework.azure import AzureAIAgentClient
from azure.identity.aio import AzureCliCredential
async def main():
async with AzureCliCredential() as credential:
chat_client = AzureAIAgentClient(credential=credential)
# Create the memory provider
memory_provider = UserInfoMemory(chat_client)
# Create the agent with memory
async with ChatAgent(
chat_client=chat_client,
instructions="You are a friendly assistant. Always address the user by their name.",
context_providers=memory_provider,
) as agent:
# Create a new thread for the conversation
thread = agent.get_new_thread()
print(await agent.run("Hello, what is the square root of 9?", thread=thread))
print(await agent.run("My name is Ruaidhrí", thread=thread))
print(await agent.run("I am 20 years old", thread=thread))
# Access the memory component via the thread's context_providers attribute and inspect the memories
if thread.context_provider:
user_info_memory = thread.context_provider.providers[0]
if isinstance(user_info_memory, UserInfoMemory):
print()
print(f"MEMORY - User Name: {user_info_memory.user_info.name}")
print(f"MEMORY - User Age: {user_info_memory.user_info.age}")
if __name__ == "__main__":
asyncio.run(main())