Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
I provider di contesto vengono eseguiti in occasione di ogni invocazione per aggiungere contesto prima dell'esecuzione ed elaborare i dati dopo l'esecuzione.
Annotazioni
Per un elenco dei provider di contesto predefiniti che è possibile usare con l'agente, vedere Integrazioni del provider di contesto.
Modello predefinito
Configurare i provider tramite le opzioni del costruttore durante la creazione di un agente.
AIContextProvider è il punto di estensione predefinito per l'arricchimento di memoria/contesto.
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));
Suggerimento
Per un elenco delle implementazioni predefinite AIContextProvider , vedere Integrazioni del provider di contesto.
Il modello regolare consiste nel configurare i provider tramite context_providers=[...] durante la creazione di un agente.
InMemoryHistoryProvider è il provider di cronologia predefinito usato per la memoria conversazionale locale.
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 può aggiungere InMemoryHistoryProvider() automaticamente con l'ID "in_memory" di origine predefinito in casi specifici, ma aggiungerlo in modo esplicito quando si vuole un comportamento di memoria locale deterministico.
Memoria supportata da file tra sessioni
Usare FileMemoryProvider quando il modello deve decidere cosa archiviare e richiamare tramite file_memory_* strumenti. In Python omettere scope deriva la cartella di lavoro dall'ID sessione corrente, quindi le sessioni separate non condividono i file di memoria. Passare un elemento stabile scope, ad esempio un identificatore utente, per condividere gli stessi file di memoria tra le sessioni e scegliere un'implementazione AgentFileStore per l'archiviazione di backup.
# 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],
)
Configurare i provider tramite agent.Config.ContextProviders durante la creazione di un agente. I provider di contesto inseriscono un contesto aggiuntivo prima dell'esecuzione di ogni agente e possono rendere persistente lo stato dopo ogni esecuzione.
a := foundryprovider.NewAgent(endpoint, token, foundryprovider.ModelDeployment(model), foundryprovider.AgentConfig{
Config: agent.Config{
ContextProviders: []agent.ContextProvider{provider},
},
})
Usare provider di contesto con l'agente Harness
I modelli manuali precedenti collegano solo i provider scelti. Harness Agent assembla un set di provider ordinato quando viene creato. Usare le opzioni di costruzione di ogni SDK per disabilitare o sostituire le impostazioni predefinite e aggiungere provider aggiuntivi.
HarnessAgent abilita TodoProvider, AgentModeProvider, FileMemoryProvidere AgentSkillsProvider per impostazione predefinita. Aggiunge i provider da HarnessAgentOptions.AIContextProviders dopo tali incorporati.
HarnessAgent agent = chatClient.AsHarnessAgent(new HarnessAgentOptions
{
AIContextProviders = [new MyCustomMemoryProvider()],
DisableAgentSkillsProvider = true,
});
Usare DisableTodoProvider, DisableAgentModeProviderDisableFileMemory, e DisableAgentSkillsProvider per rimuovere le impostazioni predefinite. Configurare la modalità e le competenze con AgentModeProviderOptions e AgentSkillsSource; sostituire l'archiviazione di memoria file con FileMemoryStore. L'accesso ai file è esplicito tramite FileAccessStore e FileAccessProviderOptionse la delega in background è esplicita tramite BackgroundAgents e BackgroundAgentsProviderOptions.
AsHarnessAgent(options) e new HarnessAgent(chatClient, options) accettare lo stesso HarnessAgentOptionsoggetto .
create_harness_agent ordina prima il provider di cronologia, quindi la compattazione post-esecuzione quando abilitata, seguita da todo, modalità e provider di memoria file. La memoria del file è attivata per impostazione predefinita; competenze, accesso ai file, agenti in background e contesto della shell sono acconsentiti esplicitamente. I provider passati context_providers= vengono aggiunti per ultimo.
agent = create_harness_agent(
client,
context_providers=[UserPreferenceProvider()],
disable_mode=True,
skills_paths=["./skills"],
)
Usare history_provider, todo_providere mode_provider per sostituire le impostazioni predefinite, con disable_todo, disable_modee disable_file_memory come rifiuto esplicito. Usare file_memory_store per sostituire l'archivio predefinito {cwd}/agent-file-memory . Abilitare i provider facoltativi con file_access_store, skills_provider o skills_pathsbackground_agents, e shell_executor. I relativi parametri di installazione configurano autorizzazioni, istruzioni e comportamento dell'ambiente.
L'agente Harness non è attualmente disponibile in Go SDK. Aggiungere provider di contesto in modo esplicito tramite agent.Config.ContextProviders.
Provider di contesto personalizzato
Usare provider di contesto personalizzati quando è necessario inserire istruzioni dinamiche/messaggi/strumenti o estrarre lo stato dopo l'esecuzione.
La classe base per i provider di contesto è Microsoft.Agents.AI.AIContextProvider.
I provider di contesto partecipano alla pipeline dell'agente, hanno la possibilità di contribuire o ignorare i messaggi di input dell'agente e possono estrarre informazioni dai nuovi messaggi.
AIContextProvider dispone di vari metodi virtuali che possono essere sovrascritti per implementare il proprio provider di contesto personalizzato.
Per altre informazioni su cosa eseguire l'override, vedere le diverse opzioni di implementazione seguenti.
AIContextProvider Stato
Un'istanza AIContextProvider viene collegata a un agente e la stessa istanza viene usata per tutte le sessioni.
Ciò significa che AIContextProvider non deve archiviare alcuno stato specifico della sessione nell'istanza del provider.
Può AIContextProvider avere un riferimento a un client del servizio di memoria in un campo, ma non deve avere un ID per il set specifico di memorie in un campo.
In alternativa, AIContextProvider può archiviare qualsiasi valore specifico della sessione, ad esempio ID memoria, messaggi o qualsiasi altro elemento rilevante in AgentSession se stesso. Ai metodi virtuali su AIContextProvider viene passato un riferimento all'oggetto corrente AIAgent e AgentSession.
Per consentire facilmente l'archiviazione dello stato tipizzato in AgentSession, viene fornita una classe di utilità.
// 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);
Implementazione semplice AIContextProvider
L'implementazione più semplice AIContextProvider esegue in genere l'override di due metodi:
- AIContextProvider.ProvideAIContextAsync : caricare i dati pertinenti e restituire istruzioni aggiuntive, messaggi o strumenti.
- AIContextProvider.StoreAIContextAsync : estrarre tutti i dati rilevanti da nuovi messaggi e archivi.
Di seguito è riportato un esempio di semplice AIContextProvider integrazione con un servizio di memoria.
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; }
}
}
Implementazione avanzata AIContextProvider
Un'implementazione più avanzata potrebbe scegliere di eseguire l'override dei metodi seguenti:
- AIContextProvider.InvokingCoreAsync - Chiamato prima che l'agente richiami l'LLM e consenta di modificare l'elenco dei messaggi di richiesta, gli strumenti e le istruzioni.
- AIContextProvider.InvokedCoreAsync : chiamato dopo che l'agente ha richiamato LLM e consente l'accesso a tutti i messaggi di richiesta e risposta.
AIContextProvider fornisce implementazioni di base di InvokingCoreAsync e InvokedCoreAsync.
L'implementazione InvokingCoreAsync di base esegue le operazioni seguenti:
- filtra la lista dei messaggi in ingresso a includere solo quelli passati al chiamante dall'agente. Si noti che questo filtro può essere sottoposto a override tramite il
provideInputMessageFilterparametro nelAIContextProvidercostruttore. - chiamate
ProvideAIContextAsynccon i messaggi di richiesta filtrati, gli strumenti e le istruzioni esistenti. - stampa tutti i messaggi restituiti da
ProvideAIContextAsynccon informazioni di origine, indicando che questi messaggi provengono da questo provider di contesto. - unisce i messaggi, gli strumenti e le istruzioni restituiti da
ProvideAIContextAsynccon quelli esistenti, per produrre l'input che verrà usato dall'agente. Messaggi, strumenti e istruzioni vengono aggiunti a quelli esistenti.
La InvokedCoreAsync base esegue le operazioni seguenti:
- controlla se l'esecuzione non è riuscita e, in caso affermativo, restituisce senza eseguire ulteriori elaborazioni.
- filtra la lista dei messaggi in ingresso a includere solo quelli passati al chiamante dall'agente. Si noti che questo filtro può essere sottoposto a override tramite il
storeInputMessageFilterparametro nelAIContextProvidercostruttore. - passa i messaggi di richiesta filtrati e tutti i messaggi di risposta a
StoreAIContextAsyncper l'archiviazione.
È possibile eseguire l'override di questi metodi per implementare un AIContextProvider, tuttavia, questo richiede che l'implementatore stesso fornisca la funzionalità di base appropriata.
Di seguito è riportato un esempio di implementazione di questo tipo.
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(".")
Annotazioni
ContextProvider e HistoryProvider sono le classi di base di Python canoniche.
I provider di contesto possono anche aggiungere middleware di chat o funzione per la chiamata corrente chiamando context.extend_middleware(self.source_id, middleware). L'agente appiattisce tali aggiunte con context.get_middleware() e le applica nell'ordine del provider prima di richiamare il client di chat.
Selezione dinamica degli strumenti
I fornitori di contesto possono aggiungere strumenti per l'invocazione corrente con context.extend_tools(self.source_id, tools). Per il caricamento progressivo degli strumenti durante un ciclo di chiamata di funzione, vedere l'esempio di dynamic_tool_exposure. Per i bundle degli strumenti gestiti, vedere Microsoft Casella degli strumenti Foundry.
Provider di cronologia personalizzato
I provider di cronologia sono provider di contesto specializzati per il caricamento o l'archiviazione dei messaggi.
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])
Importante
In Python è possibile configurare più provider di cronologia, ma solo uno deve usare load_messages=True.
Usare provider aggiuntivi per la diagnostica/valutazione con load_messages=False e store_context_messages=True in modo da acquisire il contesto da altri provider insieme all'input/output.
Se è necessaria la cronologia locale per mantenere in modo permanente ogni chiamata di modello in un ciclo di strumenti, vedere Archiviazione.
Modello di esempio:
primary = DatabaseHistoryProvider(db)
audit = InMemoryHistoryProvider("audit", load_messages=False, store_context_messages=True)
agent = Agent(client=OpenAIChatClient(), context_providers=[primary, audit])
Definire un provider di contesto personalizzato con un Provide callback:
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
},
})
I provider di contesto possono leggere e scrivere lo stato della sessione:
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
},