Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Dostawcy kontekstu działają zarówno przed, jak i po każdym wywołaniu, aby dodać kontekst przed wykonaniem oraz przetworzyć dane po wykonaniu.
Note
Aby uzyskać listę wstępnie utworzonych dostawców kontekstu, których można używać z agentem, zobacz Integracje dostawcy kontekstu.
Wzorzec wbudowany
Konfigurowanie dostawców za pomocą opcji konstruktora podczas tworzenia agenta.
AIContextProvider to domyślny punkt rozszerzenia dla wzbogacania pamięci/kontekstu.
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));
Wskazówka
Aby uzyskać listę wstępnie utworzonych AIContextProvider implementacji, zobacz Integracja dostawcy kontekstu.
Regularnym wzorcem jest skonfigurowanie dostawców za pośrednictwem context_providers=[...] podczas tworzenia agenta.
InMemoryHistoryProvider jest wbudowanym dostawcą historii używanym do lokalnej pamięci konwersacyjnej.
from agent_framework import Agent, InMemoryHistoryProvider
from agent_framework.openai import OpenAIChatClient
agent = Agent(
client=OpenAIChatClient(),
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 może automatycznie dodać InMemoryHistoryProvider() z domyślnym identyfikatorem źródła "in_memory" w określonych przypadkach, ale dodaj go jawnie, jeśli chcesz uzyskać deterministyczne działanie pamięci lokalnej.
Pamięć wspierana przez pliki między sesjami
Użyj FileMemoryProvider , kiedy model powinien zdecydować, co należy przechowywać i odwoływać za pomocą file_memory_* narzędzi. W Python pominięcie scope folderu roboczego z bieżącego identyfikatora sesji, więc oddzielne sesje nie współużytkują plików pamięci. Przekaż stabilny scopeelement , taki jak identyfikator użytkownika, aby współużytkować te same pliki pamięci między sesjami i wybrać implementację AgentFileStore magazynu zapasowego.
# 1. Create the file store the provider will use to persist memory files.
# Here we use a file-system backed store rooted at a local
# ``agent-file-memory`` folder, but any AgentFileStore implementation can
# be used, e.g. InMemoryAgentFileStore or a custom blob-backed store.
memory_root = Path(__file__).parent / "agent-file-memory"
store = FileSystemAgentFileStore(memory_root)
# 2. Create the FileMemoryProvider over that store.
# The ``scope`` determines the scope and lifetime of the memories:
# - A stable scope, like the per-user one below, gives durable memories
# shared by every session for that user. That is what allows the second
# conversation further down to recall what the user said in the first.
# - Omitting ``scope`` (the default) isolates memories to a single session
# (the working folder is derived from the session id).
file_memory_provider = FileMemoryProvider(store, scope=f"users/{USER_ID}")
# 3. Attach the provider to the agent so it gets the file_memory_* tools.
agent = Agent(
client=client,
name="TravelAssistant",
instructions=(
"You are a helpful travel assistant. Remember what the user tells you about "
"themselves so that you can give better recommendations later."
),
context_providers=[file_memory_provider],
)
Skonfiguruj dostawców za pomocą agent.Config.ContextProviders podczas tworzenia agenta. Dostawcy kontekstu wprowadzają dodatkowy kontekst przed każdym uruchomieniem agenta i mogą utrwalać stan po każdym uruchomieniu.
a := foundryprovider.NewAgent(endpoint, token, foundryprovider.ModelDeployment(model), foundryprovider.AgentConfig{
Config: agent.Config{
ContextProviders: []agent.ContextProvider{provider},
},
})
Używanie dostawców kontekstu z agentem uprzęży
Powyższe wzorce ręczne dołączają tylko wybranego dostawcę. Uprzęży agenta tworzy uporządkowany zestaw dostawcy podczas jego tworzenia. Użyj opcji konstruowania poszczególnych zestawów SDK, aby wyłączyć lub zastąpić wartości domyślne i dołączyć dodatkowych dostawców.
HarnessAgent domyślnie TodoProviderwłącza , AgentModeProvider, FileMemoryProvideri AgentSkillsProvider . Dołącza dostawców z HarnessAgentOptions.AIContextProviders tych wbudowanych.
HarnessAgent agent = chatClient.AsHarnessAgent(new HarnessAgentOptions
{
AIContextProviders = [new MyCustomMemoryProvider()],
DisableAgentSkillsProvider = true,
});
Użyj DisableTodoProvider, , DisableFileMemoryDisableAgentModeProvideri DisableAgentSkillsProvider , aby usunąć wartości domyślne. Skonfiguruj tryb i umiejętności za pomocą AgentModeProviderOptions polecenia i AgentSkillsSource; zastąp magazyn pamięci plików ciągiem FileMemoryStore. Dostęp do plików jest opt-in through i , a delegowanie w tle jest wyrażane za pośrednictwem FileAccessStoreBackgroundAgents i BackgroundAgentsProviderOptions.FileAccessProviderOptions
AsHarnessAgent(options) i new HarnessAgent(chatClient, options) zaakceptuj ten sam HarnessAgentOptionselement .
create_harness_agent najpierw zamawia dostawcę historii, a następnie po uruchomieniu kompaktowanie po włączeniu, a następnie dostawcy zadań do wykonania, trybu i pamięci plików. Pamięć pliku jest domyślnie włączona; umiejętności, dostęp do plików, agenci w tle i kontekst powłoki są opt-in. Dostawcy przekazywane context_providers= są ostatnio dołączani.
agent = create_harness_agent(
client,
context_providers=[UserPreferenceProvider()],
disable_mode=True,
skills_paths=["./skills"],
)
Użyj history_providerwartości , todo_provideri mode_provider , aby zastąpić te wartości domyślne, wartościami disable_todo, disable_modei disable_file_memory jako rezygnacjami. Użyj polecenia file_memory_store , aby zastąpić magazyn domyślny {cwd}/agent-file-memory . Włącz opcjonalnych dostawców z parametrami file_access_store, skills_provider lub skills_pathsbackground_agents, i shell_executor; ich powiązanymi parametrami konfiguracji konfigurują uprawnienia, instrukcje i zachowanie środowiska.
Agent platformy Harness nie jest obecnie dostępny w zestawie SDK języka Go. Dodaj dostawców kontekstu jawnie za pomocą polecenia agent.Config.ContextProviders.
Niestandardowy dostawca kontekstu
Użyj niestandardowych dostawców kontekstu, gdy musisz wprowadzić instrukcje dynamiczne/komunikaty/narzędzia lub wyodrębnić stan po uruchomieniu.
Klasa bazowa dla dostawców kontekstu to Microsoft.Agents.AI.AIContextProvider.
Dostawcy kontekstu uczestniczą w potoku danych agenta, mogą współtworzyć lub zastępować wiadomości wejściowe agenta i mogą wyodrębniać informacje z nowych wiadomości.
AIContextProvider ma różne metody wirtualne, które można zastąpić, aby zaimplementować własnego niestandardowego dostawcę kontekstu.
Zobacz poniższe różne opcje implementacji, aby uzyskać więcej informacji o tym, co można nadpisać.
AIContextProvider stan
Instancja AIContextProvider jest przypisana do agenta i ta sama instancja będzie używana we wszystkich sesjach.
Oznacza to, że element AIContextProvider nie powinien przechowywać żadnego stanu określonej sesji w wystąpieniu dostawcy.
Element AIContextProvider może mieć odwołanie do klienta usługi pamięci w polu, ale nie powinien mieć identyfikatora określonego zestawu pamięci w polu.
Zamiast tego AIContextProvider może przechowywać dowolne wartości specyficzne dla sesji, takie jak identyfikatory pamięci, komunikaty lub inne elementy, które są istotne wewnątrz AgentSession. Wszystkim metodom wirtualnym na AIContextProvider jest przekazywane odwołanie do bieżącego AIAgent i AgentSession.
Aby łatwo przechowywać określony typ stanu w AgentSession, udostępniana jest klasa narzędziowa:
// 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);
Prosta implementacja AIContextProvider
Najprostsza AIContextProvider implementacja zwykle zastępuje dwie metody:
- AIContextProvider.ProvideAIContextAsync — ładowanie odpowiednich danych i zwracanie dodatkowych instrukcji, komunikatów lub narzędzi.
- AIContextProvider.StoreAIContextAsync — wyodrębnianie odpowiednich danych z nowych wiadomości i ich przechowywanie.
Oto prosty przykład AIContextProvider, integrujący się z usługą pamięci.
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; }
}
}
Implementacja zaawansowana AIContextProvider
Bardziej zaawansowana implementacja może zastąpić następujące metody:
- AIContextProvider.InvokingCoreAsync — wywoływana przed wywołaniem przez agenta modułu LLM i umożliwia zmodyfikowanie listy komunikatów żądania, narzędzi i instrukcji.
- AIContextProvider.InvokedCoreAsync — wywoływana po wywołaniu agenta LLM i umożliwia dostęp do wszystkich komunikatów żądania i odpowiedzi.
AIContextProvider Udostępnia podstawowe implementacje elementów InvokingCoreAsync i InvokedCoreAsync.
Implementacja podstawowa InvokingCoreAsync wykonuje następujące czynności:
- filtruje listę komunikatów wejściowych, aby zawierała tylko te przekazywane do agenta przez wywołującego. Należy pamiętać, że ten filtr można zastąpić za pomocą parametru
provideInputMessageFilterw konstruktorzeAIContextProvider. - wywołuje
ProvideAIContextAsyncz użyciem przefiltrowanych komunikatów żądania, istniejących narzędzi i instrukcji. - oznacza wszystkie komunikaty zwracane przez
ProvideAIContextAsyncinformacjami źródłowymi, co oznacza, że te komunikaty pochodzą od tego dostawcy kontekstu. - scala komunikaty, narzędzia i instrukcje zwracane przez
ProvideAIContextAsyncprogram z istniejącymi, aby utworzyć dane wejściowe, które będą używane przez agenta. Komunikaty, narzędzia i instrukcje są dołączane do istniejących.
Baza InvokedCoreAsync wykonuje następujące czynności:
- sprawdza, czy przebieg zakończył się niepowodzeniem, a jeśli tak, zwraca bez dalszego przetwarzania.
- filtruje listę komunikatów wejściowych, aby zawierała tylko te przekazywane do agenta przez wywołującego. Należy pamiętać, że ten filtr można zastąpić za pomocą parametru
storeInputMessageFilterw konstruktorzeAIContextProvider. - przekazuje przefiltrowane komunikaty żądań i wszystkie komunikaty odpowiedzi do
StoreAIContextAsyncw celu przechowywania.
Można zastąpić te metody, aby zaimplementować element AIContextProvider, jednak wymaga to, aby implementator samodzielnie zaimplementował podstawową funkcjonalność.
Oto przykład takiej implementacji.
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(".")
Note
ContextProvider i HistoryProvider są kanonicznymi klasami podstawowymi Pythona.
Dostawcy kontekstu mogą również dodawać oprogramowanie pośredniczące czatu lub funkcji dla bieżącego wywołania, wywołując metodę context.extend_middleware(self.source_id, middleware). Agent spłaszcza te dodatki context.get_middleware() i stosuje je w kolejności dostawcy, zanim wywoła klienta czatu.
Wybór narzędzia dynamicznego
Dostawcy kontekstu mogą dodawać narzędzia dla bieżącego wywołania za pomocą polecenia context.extend_tools(self.source_id, tools). Aby zapoznać się ze stopniowym ładowaniem narzędzi w pętli wywołań funkcji, zobacz przykład dynamic_tool_exposure. W przypadku pakietów narzędzi zarządzanych zobacz Microsoft Przybornik usługi Foundry.
Niestandardowy dostawca historii
Dostawcy historii to dostawcy kontekstu wyspecjalizowani do ładowania/przechowywania komunikatów.
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("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("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])
Ważna
W języku Python można skonfigurować wielu dostawców historii, ale tylko jeden powinien używać load_messages=True.
Użyj dodatkowych dostawców do diagnostyki/oceny z load_messages=False i store_context_messages=True, aby przechwytywali kontekst od innych dostawców wraz z danymi wejściowymi/wyjściowymi.
Jeśli potrzebujesz zachować historię lokalną dla każdego wywołania modelu w pętli narzędzi, zobacz Magazyn.
Przykładowy wzorzec:
primary = DatabaseHistoryProvider(db)
audit = InMemoryHistoryProvider("audit", load_messages=False, store_context_messages=True)
agent = Agent(client=OpenAIChatClient(), context_providers=[primary, audit])
Zdefiniuj własnego dostawcę kontekstu za pomocą wywołania zwrotnego Provide:
import (
"context"
"github.com/microsoft/agent-framework-go/agent"
"github.com/microsoft/agent-framework-go/message"
)
provider := agent.NewContextProvider(agent.ContextProviderConfig{
SourceID: "user_memory",
Provide: func(ctx context.Context, invoking agent.InvokingContext) ([]*message.Message, []agent.Option, error) {
return nil, []agent.Option{agent.WithInstructions("User prefers short answers.")}, nil
},
})
Dostawcy kontekstu mogą odczytywać i zapisywać stan sesji:
Provide: func(ctx context.Context, invoking agent.InvokingContext) ([]*message.Message, []agent.Option, error) {
session, _ := agent.GetOption(invoking.Options, agent.WithSession)
var state MyState
_, _ = session.Get("my_key", &state)
return nil, nil, nil
},
Store: func(ctx context.Context, invoked agent.InvokedContext) error {
session, _ := agent.GetOption(invoked.Options, agent.WithSession)
session.Set("my_key", updatedState)
return nil
},