Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Penyedia konteks menjalankan setiap pemanggilan untuk menambahkan konteks sebelum eksekusi dan memproses data setelah eksekusi.
Nota
Untuk daftar penyedia konteks bawaan yang dapat Anda gunakan dengan agen Anda, lihat Integrasi
Pola bawaan
Konfigurasikan penyedia melalui opsi konstruktor saat membuat agen.
AIContextProvider adalah titik ekstensi bawaan untuk pengayaan memori/konteks.
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));
Petunjuk / Saran
Untuk daftar implementasi bawaan AIContextProvider , lihat Integrasi
Pola umum adalah mengonfigurasi penyedia melalui context_providers=[...] saat membuat agen.
InMemoryHistoryProvider adalah penyedia riwayat bawaan yang digunakan untuk memori percakapan lokal.
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 dapat menambahkan InMemoryHistoryProvider("memory") secara otomatis dalam kasus tertentu, tetapi menambahkannya secara eksplisit saat Anda menginginkan perilaku memori lokal deterministik.
Penyedia konteks kustom
Gunakan penyedia konteks kustom saat Anda perlu menyuntikkan instruksi/pesan/alat dinamis atau mengekstrak status setelah dijalankan.
Kelas dasar untuk penyedia konteks Microsoft.Agents.AI.AIContextProvider.
Penyedia konteks berpartisipasi dalam alur agen, memiliki kemampuan untuk berkontribusi atau mengambil alih pesan input agen dan dapat mengekstrak informasi dari pesan baru.
AIContextProvider memiliki berbagai metode virtual yang dapat didefinisikan ulang sehingga Anda dapat mengimplementasikan penyedia konteks kustom Anda sendiri.
Lihat berbagai opsi implementasi di bawah ini untuk informasi selengkapnya tentang apa yang perlu diganti.
AIContextProvider Status
Instans AIContextProvider dilampirkan ke agen dan instans yang sama akan digunakan untuk semua sesi.
Ini berarti bahwa AIContextProvider tidak boleh menyimpan status spesifik sesi apa pun dalam instans penyedia.
AIContextProvider mungkin memiliki referensi ke klien layanan memori dalam sebuah bidang, namun tidak seharusnya memiliki ID untuk set memori tertentu dalam bidang tersebut.
Sebagai gantinya, AIContextProvider dapat menyimpan nilai-nilai spesifik sesi, seperti id memori, pesan, atau hal-hal lain yang relevan di dalam AgentSession. Semua metode virtual diteruskan sebagai referensi ke AIContextProvider dan AIAgent saat ini.
Untuk mengaktifkan penyimpanan status yang di ketik dengan mudah di AgentSessionkelas utilitas disediakan:
// 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);
Implementasi sederhana AIContextProvider
Implementasi paling AIContextProvider sederhana biasanya akan mengambil alih dua metode:
- AIContextProvider.ProvideAIContextAsync - Muat data yang relevan dan kembalikan instruksi, pesan, atau alat tambahan.
- AIContextProvider.StoreAIContextAsync - Mengekstrak data yang relevan dari pesan baru dan menyimpan data tersebut.
Berikut adalah contoh sederhana AIContextProvider yang terintegrasi dengan layanan memori.
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; }
}
}
Implementasi tingkat lanjut AIContextProvider
Implementasi yang lebih canggih dapat memilih untuk mengambil alih metode berikut:
- AIContextProvider.InvokingCoreAsync - Dipanggil sebelum agen memanggil LLM dan memungkinkan daftar pesan permintaan, alat, dan instruksi untuk dimodifikasi.
- AIContextProvider.InvokedCoreAsync - Dipanggil setelah agen memanggil LLM dan memungkinkan akses ke semua pesan permintaan dan respons.
AIContextProvider menyediakan implementasi dasar untuk InvokingCoreAsync dan InvokedCoreAsync.
Implementasi InvokingCoreAsync dasar melakukan hal berikut:
- memfilter daftar pesan input untuk hanya pesan yang diteruskan ke agen oleh pemanggil. Perhatikan bahwa filter ini dapat digantikan melalui parameter
provideInputMessageFilterpada konstruktorAIContextProvider. - Melakukan panggilan dengan pesan permintaan yang telah difilter, serta alat dan instruksi yang ada.
- menandai semua pesan yang dikembalikan oleh
ProvideAIContextAsyncdengan informasi sumber, menunjukkan bahwa pesan ini berasal dari penyedia konteks ini. - menggabungkan pesan, alat, dan instruksi yang dikembalikan oleh
ProvideAIContextAsyncdengan pesan yang ada, untuk menghasilkan input yang akan digunakan oleh agen. Pesan, alat, dan instruksi ditambahkan ke pesan yang sudah ada.
Basis InvokedCoreAsync melakukan hal berikut:
- memeriksa apakah eksekusi gagal dan jika demikian, kembali tanpa melakukan pemrosesan lebih lanjut.
- memfilter daftar pesan input untuk hanya pesan yang diteruskan ke agen oleh pemanggil. Perhatikan bahwa filter ini dapat digantikan melalui parameter
storeInputMessageFilterpada konstruktorAIContextProvider. - meneruskan pesan permintaan yang difilter dan semua pesan respons ke
StoreAIContextAsyncuntuk penyimpanan.
Dimungkinkan untuk mengganti metode ini untuk mengimplementasikan AIContextProvider, namun ini membutuhkan pelaksana untuk mengimplementasikan fungsi dasar tersebut sendiri sesuai kebutuhan.
Berikut adalah contoh implementasi seperti itu.
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(".")
Nota
ContextProvider dan HistoryProvider adalah kelas dasar Python kanonis.
BaseContextProvider dan BaseHistoryProvider masih ada sebagai alias yang sudah usang demi menjaga kompatibilitas, tetapi penyedia baru sebaiknya mewarisi dari nama baru.
Penyedia konteks juga dapat menambahkan middleware percakapan atau fungsi untuk pemanggilan saat ini dengan memanggil context.extend_middleware(self.source_id, middleware). Agen mengharmonisasi penambahan tersebut dengan context.get_middleware() dan menerapkannya sesuai urutan penyedia sebelum memanggil klien obrolan.
Penyedia riwayat kustom
Penyedia riwayat adalah penyedia konteks khusus untuk memuat/menyimpan pesan.
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])
Penting
Dalam Python, Anda dapat mengonfigurasi beberapa penyedia riwayat, tetapi hanya satu harus menggunakan load_messages=True.
Gunakan penyedia tambahan untuk diagnostik/evaluasi dengan load_messages=False dan store_context_messages=True sehingga mereka mengumpulkan konteks dari penyedia lain bersama dengan input/output.
Jika Anda memerlukan riwayat lokal untuk melekat pada setiap pemanggilan model di dalam putaran alat, lihat Penyimpanan.
Contoh pola:
primary = DatabaseHistoryProvider(db)
audit = InMemoryHistoryProvider("audit", load_messages=False, store_context_messages=True)
agent = OpenAIChatClient().as_agent(context_providers=[primary, audit])