Aracılığıyla paylaş


Bağlam Sağlayıcıları

Bağlam sağlayıcıları yürütmeden önce bağlam eklemek ve yürütmeden sonra verileri işlemek için her çağrının etrafında çalışır.

Uyarı

Aracınızla birlikte kullanabileceğiniz önceden oluşturulmuş bağlam sağlayıcılarının listesi için bkz. Tümleştirmeler

Yerleşik desen

Aracı oluştururken oluşturucu seçenekleri aracılığıyla sağlayıcıları yapılandırın. AIContextProvider , bellek/bağlam zenginleştirmesi için yerleşik uzantı noktasıdır.

AIAgent agent = new OpenAIClient("<your_api_key>")
    .GetChatClient(modelName)
    .AsAIAgent(new ChatClientAgentOptions()
    {
        ChatOptions = new() { Instructions = "You are a helpful assistant." },
        AIContextProviders = [
            new MyCustomMemoryProvider()
        ],
    });

AgentSession session = await agent.CreateSessionAsync();
Console.WriteLine(await agent.RunAsync("Remember my name is Alice.", session));

Tavsiye

Önceden oluşturulmuş AIContextProvider uygulamaların listesi için bkz. Tümleştirmeler

Normal düzen, bir aracı oluştururken context_providers=[...] üzerinden sağlayıcıları yapılandırmaktır.

InMemoryHistoryProvider , yerel konuşma belleği için kullanılan yerleşik geçmiş sağlayıcısıdır.

from agent_framework import InMemoryHistoryProvider
from agent_framework.openai import OpenAIChatClient

agent = OpenAIChatClient().as_agent(
    name="MemoryBot",
    instructions="You are a helpful assistant.",
    context_providers=[InMemoryHistoryProvider("memory", load_messages=True)],
)

session = agent.create_session()
await agent.run("Remember that I prefer vegetarian food.", session=session)

RawAgent belirli durumlarda otomatik olarak ekleyebilir InMemoryHistoryProvider("memory") , ancak belirleyici yerel bellek davranışı istediğinizde açıkça ekleyebilirsiniz.

Özel bağlam sağlayıcısı

Çalıştırmalardan sonra dinamik yönergeler/iletiler/araçlar eklemeniz veya durumu ayıklamanız gerektiğinde özel bağlam sağlayıcılarını kullanın.

Bağlam sağlayıcıları için temel sınıf Microsoft.Agents.AI.AIContextProvider. Bağlam sağlayıcıları aracı işlem hattına katılır, aracı giriş iletilerine katkıda bulunabilir veya bu iletileri geçersiz kılabilir ve yeni iletilerden bilgi ayıklayabilir. AIContextProvider kendi özel bağlam sağlayıcınızı uygulamak için geçersiz kılınabilecek çeşitli sanal yöntemlere sahiptir. Daha fazla bilgi için, neyin geçersiz kılınacağını anlamak amacıyla aşağıdaki farklı uygulama seçeneklerine bakın.

AIContextProvider Durum

Bir AIContextProvider örnek bir aracıya eklenir ve tüm oturumlar için aynı örnek kullanılır. Bu, sağlayıcı örneğinde AIContextProvider oturuma özgü bir durum depolamaması gerektiği anlamına gelir. AIContextProvider bir alanda bellek hizmeti istemcisine referansı olabilir, ancak alandaki belirli bir bellek kümesine özgü bir kimliği olmamalıdır.

Bunun yerine, AIContextProvider bellek kimlikleri, iletiler veya kendi içinde ilgili başka herhangi bir şey gibi oturuma AgentSession özgü değerleri depolayabilir. AIContextProvider üzerindeki sanal yöntemlerin tümüne, geçerli AIAgent ve AgentSession için bir başvuru geçirilir.

Belirtilmiş türdeki durumu AgentSession içinde kolayca depolamak için bir yardımcı sınıf sağlanır.

// First define a type containing the properties to store in state
internal class MyCustomState
{
    public string? MemoryId { get; set; }
}

// Create the helper
var sessionStateHelper = new ProviderSessionState<MyCustomState>(
    // stateInitializer is called when there is no state in the session for this AIContextProvider yet
    stateInitializer: currentSession => new MyCustomState() { MemoryId = Guid.NewGuid().ToString() },
    // The key under which to store state in the session for this provider. Make sure it does not clash with the keys of other providers.
    stateKey: this.GetType().Name,
    // An optional jsonSerializerOptions to control the serialization/deserialization of the custom state object
    jsonSerializerOptions: myJsonSerializerOptions);

// Using the helper you can read state:
MyCustomState state = sessionStateHelper.GetOrInitializeState(session);
Console.WriteLine(state.MemoryId);

// And write state:
sessionStateHelper.SaveState(session, state);

Basit AIContextProvider uygulama

En basit AIContextProvider uygulama genellikle iki yöntemi geçersiz kılar:

  • AIContextProvider.ProvideAIContextAsync - İlgili verileri yükleyin ve ek yönergeler, iletiler veya araçlar döndürin.
  • AIContextProvider.StoreAIContextAsync - Yeni iletilerden ve depodan ilgili verileri ayıklayın.

Burada, bir bellek hizmetiyle tümleşen basit AIContextProvider bir örnek verilmiştir.

internal sealed class SimpleServiceMemoryProvider : AIContextProvider
{
    private readonly ProviderSessionState<State> _sessionState;
    private readonly ServiceClient _client;

    public SimpleServiceMemoryProvider(ServiceClient client, Func<AgentSession?, State>? stateInitializer = null)
        : base(null, null)
    {
        this._sessionState = new ProviderSessionState<State>(
            stateInitializer ?? (_ => new State()),
            this.GetType().Name);
        this._client = client;
    }

    public override string StateKey => this._sessionState.StateKey;

    protected override ValueTask<AIContext> ProvideAIContextAsync(InvokingContext context, CancellationToken cancellationToken = default)
    {
        var state = this._sessionState.GetOrInitializeState(context.Session);

        if (state.MemoriesId == null)
        {
            // No stored memories yet.
            return new ValueTask<AIContext>(new AIContext());
        }

        // Find memories that match the current user input.
        var memories = this._client.LoadMemories(state.MemoriesId, string.Join("\n", context.AIContext.Messages?.Select(x => x.Text) ?? []));

        // Return a new message that contains the text from any memories that were found.
        return new ValueTask<AIContext>(new AIContext
        {
            Messages = [new ChatMessage(ChatRole.User, "Here are some memories to help answer the user question: " + string.Join("\n", memories.Select(x => x.Text)))]
        });
    }

    protected override async ValueTask StoreAIContextAsync(InvokedContext context, CancellationToken cancellationToken = default)
    {
        var state = this._sessionState.GetOrInitializeState(context.Session);
        // Create a memory container in the service for this session
        // and save the returned id in the session.
        state.MemoriesId ??= this._client.CreateMemoryContainer();
        this._sessionState.SaveState(context.Session, state);

        // Use the service to extract memories from the user input and agent response.
        await this._client.StoreMemoriesAsync(state.MemoriesId, context.RequestMessages.Concat(context.ResponseMessages ?? []), cancellationToken);
    }

    public class State
    {
        public string? MemoriesId { get; set; }
    }
}

Gelişmiş AIContextProvider uygulama

Daha gelişmiş bir uygulama aşağıdaki yöntemleri geçersiz kılmayı seçebilir:

  • AIContextProvider.InvokingCoreAsync - Aracı LLM'yi çağırmadan önce çağrılır ve istek iletisi listesinin, araçların ve yönergelerin değiştirilmesine izin verir.
  • AIContextProvider.InvokedCoreAsync - Aracı LLM'yi çağırdıktan sonra çağrılır ve tüm istek ve yanıt iletilerine erişime izin verir.

AIContextProvider, InvokingCoreAsync ve InvokedCoreAsync temel uygulamalarını sağlar.

InvokingCoreAsync Temel uygulama aşağıdakileri yapar:

  • giriş iletisi listesini yalnızca arayanın aracıya iletmiş olduğu iletilere filtreler. Bu filtrenin oluşturucudaki provideInputMessageFilterAIContextProvider parametresi aracılığıyla geçersiz kılınabileceğini unutmayın.
  • ProvideAIContextAsync, filtrelenmiş istek iletileriyle, mevcut araçlar ve yönergelerle çağrılır.
  • tarafından döndürülen ProvideAIContextAsync tüm iletileri kaynak bilgileriyle damgalar ve bu iletilerin bu bağlam sağlayıcısından geldiğini belirtir.
  • aracı tarafından kullanılacak girişi oluşturmak için tarafından ProvideAIContextAsync döndürülen iletileri, araçları ve yönergeleri mevcut olanlarla birleştirir. İletiler, araçlar ve yönergeler mevcut olanların sonuna eklenir.

Temel InvokedCoreAsync aşağıdakileri yapar:

  • çalıştırmanın başarısız olup olmadığını denetler ve başarısız olursa, daha fazla işlem yapmadan döndürür.
  • giriş iletisi listesini yalnızca arayanın aracıya iletmiş olduğu iletilere filtreler. Bu filtrenin oluşturucudaki storeInputMessageFilterAIContextProvider parametresi aracılığıyla geçersiz kılınabileceğini unutmayın.
  • Filtrelenmiş istek iletilerini ve tüm yanıt iletilerini depolama için StoreAIContextAsync öğesine geçirir.

Bir AIContextProvider uygulamak için bu yöntemleri geçersiz kılmak mümkündür, ancak bunun için uygulayanın temel işlevselliği uygun bir şekilde gerçekleştirmesi gerekir. Burada böyle bir uygulama örneği verilmiştir.

internal sealed class AdvancedServiceMemoryProvider : AIContextProvider
{
    private readonly ProviderSessionState<State> _sessionState;
    private readonly ServiceClient _client;

    public AdvancedServiceMemoryProvider(ServiceClient client, Func<AgentSession?, State>? stateInitializer = null)
        : base(null, null)
    {
        this._sessionState = new ProviderSessionState<State>(
            stateInitializer ?? (_ => new State()),
            this.GetType().Name);
        this._client = client;
    }

    public override string StateKey => this._sessionState.StateKey;

    protected override async ValueTask<AIContext> InvokingCoreAsync(InvokingContext context, CancellationToken cancellationToken = default)
    {
        var state = this._sessionState.GetOrInitializeState(context.Session);

        if (state.MemoriesId == null)
        {
            // No stored memories yet.
            return new AIContext();
        }

        // We only want to search for memories based on user input, and exclude chat history or other AI context provider messages.
        var filteredInputMessages = context.AIContext.Messages?.Where(m => m.GetAgentRequestMessageSourceType() == AgentRequestMessageSourceType.External);

        // Find memories that match the current user input.
        var memories = this._client.LoadMemories(state.MemoriesId, string.Join("\n", filteredInputMessages?.Select(x => x.Text) ?? []));

        // Create a message for the memories, and stamp it to indicate where it came from.
        var memoryMessages =
            [new ChatMessage(ChatRole.User, "Here are some memories to help answer the user question: " + string.Join("\n", memories.Select(x => x.Text)))]
            .Select(m => m.WithAgentRequestMessageSource(AgentRequestMessageSourceType.AIContextProvider, this.GetType().FullName!));

        // Return a new merged AIContext.
        return new AIContext
        {
            Instructions = context.AIContext.Instructions,
            Messages = context.AIContext.Messages.Concat(memoryMessages),
            Tools = context.AIContext.Tools
        };
    }

    protected override async ValueTask InvokedCoreAsync(InvokedContext context, CancellationToken cancellationToken = default)
    {
        if (context.InvokeException is not null)
        {
            return;
        }

        var state = this._sessionState.GetOrInitializeState(context.Session);
        // Create a memory container in the service for this session
        // and save the returned id in the session.
        state.MemoriesId ??= this._client.CreateMemoryContainer();
        this._sessionState.SaveState(context.Session, state);

        // We only want to store memories based on user input and agent output, and exclude messages from chat history or other AI context providers to avoid feedback loops.
        var filteredRequestMessages = context.RequestMessages.Where(m => m.GetAgentRequestMessageSourceType() == AgentRequestMessageSourceType.External);

        // Use the service to extract memories from the user input and agent response.
        await this._client.StoreMemoriesAsync(state.MemoriesId, filteredRequestMessages.Concat(context.ResponseMessages ?? []), cancellationToken);
    }

    public class State
    {
        public string? MemoriesId { get; set; }
    }
}
from typing import Any

from agent_framework import AgentSession, ContextProvider, SessionContext


class UserPreferenceProvider(ContextProvider):
    def __init__(self) -> None:
        super().__init__("user-preferences")

    async def before_run(
        self,
        *,
        agent: Any,
        session: AgentSession,
        context: SessionContext,
        state: dict[str, Any],
    ) -> None:
        if favorite := state.get("favorite_food"):
            context.extend_instructions(self.source_id, f"User's favorite food is {favorite}.")

    async def after_run(
        self,
        *,
        agent: Any,
        session: AgentSession,
        context: SessionContext,
        state: dict[str, Any],
    ) -> None:
        for message in context.input_messages:
            text = (message.text or "") if hasattr(message, "text") else ""
            if isinstance(text, str) and "favorite food is" in text.lower():
                state["favorite_food"] = text.split("favorite food is", 1)[1].strip().rstrip(".")

Uyarı

ContextProvider ve HistoryProvider kurallı Python temel sınıflarıdır. BaseContextProvider ve BaseHistoryProvider hala uyumluluk için kullanım dışı diğer adlar olarak mevcuttur, ancak yeni sağlayıcılar yeni adlardan devralmalıdır.

Bağlam sağlayıcıları, context.extend_middleware(self.source_id, middleware) çağrısını yaparak geçerli çağrı için sohbet veya işlev ara yazılımı ekleyebilir. Aracı, bu eklemeleri context.get_middleware() ile birlikte önce düzleştirir ve onları sağlayıcı sırasına göre uyguladıktan sonra sohbet istemcisini çağırır.

Özel geçmiş sağlayıcısı

Geçmiş sağlayıcıları, iletileri yüklemek/depolamak için özelleştirilmiş bağlam sağlayıcılarıdır.

from collections.abc import Sequence
from typing import Any

from agent_framework import HistoryProvider, Message


class DatabaseHistoryProvider(HistoryProvider):
    def __init__(self, db: Any) -> None:
        super().__init__("db-history", load_messages=True)
        self._db = db

    async def get_messages(
        self,
        session_id: str | None,
        *,
        state: dict[str, Any] | None = None,
        **kwargs: Any,
    ) -> list[Message]:
        key = (state or {}).get(self.source_id, {}).get("history_key", session_id or "default")
        rows = await self._db.load_messages(key)
        return [Message.from_dict(row) for row in rows]

    async def save_messages(
        self,
        session_id: str | None,
        messages: Sequence[Message],
        *,
        state: dict[str, Any] | None = None,
        **kwargs: Any,
    ) -> None:
        if not messages:
            return
        if state is not None:
            key = state.setdefault(self.source_id, {}).setdefault("history_key", session_id or "default")
        else:
            key = session_id or "default"
        await self._db.save_messages(key, [m.to_dict() for m in messages])

Önemli

Python'da birden çok geçmiş sağlayıcısını yapılandırabilirsiniz, ancak sadece biriload_messages=True kullanmalıdır. Tanılama/değerlendirmeler için load_messages=False ve store_context_messages=True ile ek sağlayıcılar kullanın; böylece giriş/çıkış ile birlikte diğer sağlayıcılardan da bağlamı yakalarlar. Bir araç döngüsündeki her model çağrısında kalıcı olması için yerel geçmişe ihtiyacınız varsa bkz. Depolama.

Örnek desen:

primary = DatabaseHistoryProvider(db)
audit = InMemoryHistoryProvider("audit", load_messages=False, store_context_messages=True)
agent = OpenAIChatClient().as_agent(context_providers=[primary, audit])

Sonraki Adımlar