Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Wichtig
Die in diesem Artikel markierten Elemente (Vorschau) sind aktuell als öffentliche Vorschau verfügbar. Diese Vorschauversion wird ohne Vereinbarung zum Servicelevel bereitgestellt und sollte nicht für Produktionsworkloads verwendet werden. Manche Features werden möglicherweise nicht unterstützt oder sind nur eingeschränkt verwendbar. Weitere Informationen finden Sie unter Supplementale Nutzungsbedingungen für Microsoft Azure Previews.
Standardmäßig erhält jeder Anrufer eine eigene gehostete Agent-Sitzung, wie in isolate hosted agent sessions pro Benutzer beschrieben. Anwendungen, die viele Benutzer bedienen – ein Teams-Bot, ein ISV-Gateway oder eine Kundensupportplattform – benötigen keine Sitzung pro Benutzer. Stattdessen ordnet ein Dienst auf mittlerer Ebene viele Benutzer einem gebundenen Pool freigegebener Sitzungen zu und identifiziert jeden Benutzer bei jedem Anruf.
In diesem Artikel wird erläutert, wie Sie Sitzungen zwischen Benutzern aus Ihrer mittleren Ebene poolen und gleichzeitig die Daten der einzelnen Benutzer innerhalb einer freigegebenen Sitzung isoliert halten.
Die Plattform isoliert den Konversationsstatus für Sie, selbst wenn Benutzer eine Sitzung gemeinsam nutzen: Eine von einem Benutzer erstellte Antwortkette kann von keinem anderen Benutzer über previous_response_id fortgesetzt werden, und context.get_history() gibt nur den Verlauf zurück, den der Benutzer der aktuellen Anfrage sehen darf. Sie verwalten zwei Dinge: die Zuordnung von Benutzern zu Sitzungen in Ihrer mittleren Schicht und die Partitionierung aller Daten, die Ihr Container selbst speichert (Dateien, Zeilen oder Cache), jenseits dieses plattformseitig verwalteten Konversationszustands.
Ein vollständiges, lauffähiges Beispiel für Sitzungsmultiplexing veranschaulicht beide Seiten – den Sessionpool der mittleren Ebene und den Container-Handler – und dieser Artikel verlinkt im Verlauf die zugehörigen Dateien.
Voraussetzungen
- Ein gehosteter Agent, der Containerprotokollversion 2.0.0 verwendet. Informationen zum Upgrade finden Sie unter Migrieren gehosteter Agents.
- Die
Microsoft.CognitiveServices/accounts/AIServices/agents/endpoints/UserIdentityImpersonation/actionBerechtigung, die der Identität Ihres Diensts auf mittlerer Ebene zugewiesen ist. Diese Berechtigung ist nicht in integrierten Rollen enthalten; sie über eine benutzerdefinierte Rolle gewähren – siehe Delegieren der Endbenutzeridentität. Ohne diese wird diex-ms-user-identity-Kopfzeile mit einem403abgelehnt. - Die Azure AI Projects-Clientbibliothek für die mittlere Ebene und das Azure AI AgentServer SDK für den Container (
azure-ai-agentserver-core2.0.0b7+ für Python oderAzure.AI.AgentServer.Core1.0.0-beta.26+ für .NET). - Ein bereitgestellter Agent, gegen den Tests ausgeführt werden können. Für lokale Ausführung wird keine Isolierung erzwungen.
Isolieren Sie zwei Benutzer in einer gemeinsamen Sitzung
Beginnen wir mit dem grundlegenden Verhalten: Zwei Benutzer – nennen wir sie Alice und Bob, die im Beispiel stellvertretend für die betroffenen Nutzer stehen – können ein agent_session_id gemeinsam nutzen, und die Plattform gewährleistet weiterhin, dass die Gespräche jedes Nutzers privat bleiben. Ihre mittlere Schicht identifiziert bei jedem Aufruf den Benutzer, in dessen Namen gehandelt wird, mit dem Header x-ms-user-identity (Delegation). Um die eigene Konversation eines Benutzers fortzusetzen, übergibt das System die vorherige Antwort dieses Benutzers als previous_response_id.
Der minimale invoke_previous_response_isolation.py Aufrufer im Beispiel sendet genau das mithilfe des agentgebundenen Antwortclients des SDK:
# Agent-bound Responses client from the Foundry SDK.
responses_client = project_client.get_openai_client(agent_name=agent_name).responses
# Target the shared session with agent_session_id, and identify the acted-for
# user with x-ms-user-identity (delegation). Pass previous_response_id to
# continue this user's own chain. Don't send x-agent-user-id; Foundry sets the
# container-side request context after it resolves the user.
kwargs = {
"input": user_message,
"stream": False,
"store": True,
"extra_body": {"agent_session_id": session_id},
"extra_headers": {"x-ms-user-identity": user_id},
}
if previous_response_id:
kwargs["previous_response_id"] = previous_response_id
response = responses_client.create(**kwargs)
Die Plattform verknüpft jede Antwortkette mit dem Benutzer, der sie erstellt hat. Wenn Bob Alices previous_response_id sendet, während er sich in derselben Sitzung befindet, schlägt der Anruf fehl – Bob kann Alices Unterhaltung nicht fortsetzen. Diese Garantie gilt ohne zusätzlichen Isolationscode in Ihrem Container.
Skalieren auf viele Benutzer mit einem Sitzungspool
Das Isolieren von zwei Benutzern in einer Sitzung ist der Baustein. Um viele Benutzer zu bedienen, poolen Sie sie über einen begrenzten Satz von Sitzungen, anstatt eine Sitzung pro Benutzer zu öffnen.
Jede Sitzung wird auf die regionalen Limits für gleichzeitige Sitzungen angerechnet, während sie aktiv einen Turn verarbeitet, sodass eine Sitzung pro Benutzer nicht skalierbar ist. Da Nutzer zwischen den Interaktionen lesen, nachdenken und tippen, macht Ihre Anfragen-Spitzenlast bei gleichzeitigen Anfragen in der Regel nur einen kleinen Bruchteil Ihrer gesamten Nutzerzahl aus. Vergrößern Sie einen Pool zu diesem Spitzenwert, ordnen Sie dann jedem Benutzer eine Sitzung darin zu, und übergeben Sie die Identität dieses Benutzers für jeden Anruf, genau wie im vorherigen Abschnitt.
Entscheiden Sie, wie Benutzer Sitzungen zugeordnet werden sollen. Zu den gängigen Strategien gehören:
- Fixiert, mit geringster Auslastung. Ein zurückgegebener Benutzer verwendet seine Sitzung wieder; neue Benutzer wechseln zur am wenigsten geladenen Sitzung. Diese Strategie verteilt die Last gleichmäßig und hält die Runden eines Benutzers zusammen. Vergrößern Sie den Pool, wenn Sitzungen eine benutzerspezifische Obergrenze erreichen.
- Hashbasiert. Weisen Sie eine Sitzung mit
hash(user_id) % pool_sizezu. Diese Strategie ist einfach und zustandslos, aber die Auslastung kann ungleichmäßig sein, und eine Änderung der Pool-Größe verteilt die Benutzer neu. - Round Robin. Verteilen Sie Anforderungen gleichmäßig über den Pool. Diese Strategie ist einfach, aber die Runden eines Benutzers können auf verschiedene Sitzungen landen.
- Gruppenbasiert. Leiten Sie nach Mandant, Team oder Region weiter, damit zusammengehörige Benutzer dieselben Sitzungen nutzen. Diese Strategie ist nützlich, wenn Benutzer in einer Gruppe denselben Kontext gemeinsam nutzen.
Der invoke_session_pool.py-Aufrufer im Beispiel implementiert die aufrufereigene Zuweisung mit zwei Strategien, sticky-fill und round-robin. Ein zurückkehrender Benutzer behält seine Sitzung immer bei; ein neuer Benutzer wird gemäß der ausgewählten Strategie zugewiesen. Das Sticky-Fill-Verfahren füllt die am geringsten ausgelastete Sitzung und öffnet nur dann eine neue, wenn jede Sitzung ihre Kapazitätsgrenze erreicht hat:
def get_session_for_user(self, user_id: str) -> str:
if user_id in self.user_to_session:
return self.user_to_session[user_id] # returning user is sticky
session_id = self._next_fill_session() # new user: place by strategy
self.user_to_session[user_id] = session_id
self.session_user_counts[session_id] += 1
return session_id
def _next_fill_session(self) -> str:
# Reuse a session with capacity; open a new one only when all are full.
session_id = next(
(s for s, count in self.session_user_counts.items()
if count < self.max_users_per_session),
None,
)
if session_id is None:
session_id = self._session_name(len(self.session_user_counts))
self.session_user_counts[session_id] = 0
return session_id
Speisen Sie die zurückgegebene Sitzungs-ID in denselben zuvor gezeigten delegierten Aufruf ein: Sie wird zu agent_session_id in extra_body, und x-ms-user-identity bleibt die benutzerspezifische Kennung.
Verarbeiten Sie die Anfrage in Ihrem Container
Im Protokoll 2.0.0 ermittelt die Plattform den Benutzer, in dessen Namen gehandelt wird, und stellt ihn Ihrem Handler über get_request_context() zur Verfügung. Validieren Sie den Kontext (im Fehlerfall den Zugriff verweigern, wenn er fehlt, z. B. bei lokalen Ausführungen), und lassen Sie dann die Plattform den benutzerspezifischen Verlauf mit context.get_history() zurückgeben. Der main.py Handler im Beispiel verwaltet keinen eigenen Konversationszustand:
from azure.ai.agentserver.core import get_request_context
@app.response_handler
async def handler(request, context, _cancellation_signal):
ctx = get_request_context()
if not (ctx.user_id and ctx.call_id):
# Hosted protocol 2.0.0 populates this context; off-platform it's absent.
raise ValueError("A user context is required on protocol 2.0.0.")
user_input = await context.get_input_text() or "Hello!"
history = await context.get_history() # platform-authorized for this user
input_items = _build_input(user_input, history)
response = _responses_client.create(model=_model, input=input_items, store=False)
return TextResponse(context, request, text=response.output_text)
Da die Plattform context.get_history() pro Anfrage autorisiert, erhält ein Benutzer in einer gemeinsamen Sitzung niemals den Gesprächsverlauf eines anderen Benutzers.
Partitionieren Sie die benutzerspezifischen Daten, die Ihr Container speichert.
Die Plattform trennt den Konversationsverlauf für Sie. Wenn Ihr Container auch eigene Daten – Dateien, Datenbankzeilen oder einen Cache – speichert, werden diese Daten nicht automatisch partitioniert. Verwende sowohl die Sitzungs-ID als auch die Benutzer-ID als Schlüssel, damit zwei Benutzer in derselben Sitzung nicht auf die Daten des jeweils anderen zugreifen können:
partition = (agent_session_id, user_id)
Warnung
Wenn Benutzer eine Sitzung freigeben, partitioniert die Plattform nicht die Daten, die Ihr Container selbst speichert. Wenn Ihr Container diese Daten nur anhand der Session-ID zuordnet, sehen alle Benutzer im Pool dieselben Daten. Geben Sie immer die Benutzer-ID in den Partitionsschlüssel ein.
Lesen Sie die Benutzer-ID aus dem anfragebezogenen Plattformkontext:
from azure.ai.agentserver.core import get_request_context
def partition_key() -> tuple[str, str]:
ctx = get_request_context()
if not ctx or not ctx.user_id:
raise PermissionError("A user context is required on protocol 2.0.0.")
return (ctx.session_id, ctx.user_id) # key all user-owned data by this
Die Plattform fügt außerdem den Benutzer als x-agent-user-id Anforderungsheader hinzu. Wenn Ihre Laufzeit den SDK-Kontext nicht verwendet, lesen Sie diesen Header direkt.
Die Plattform befüllt get_request_context().user_id unter Protokoll 2.0.0. Verwenden Sie die Sitzungs-ID niemals allein für benutzereigene Daten, wenn mehrere Benutzer die Sitzung eingeben können.
Ein ausgearbeitetes Beispiel für sitzungsbezogenen Speicher, auf dem Sie aufbauen können, finden Sie im Beispiel für einen Agenten zum Erstellen von Notizen. Es schlüsselt eine Datei pro Sitzung unter $HOME. Bei einer gemeinsam genutzten Sitzung erweitern Sie diesen Schlüssel um die Benutzer-ID aus dem Anfragekontext, damit jeder Benutzer seine eigene Partition erhält.
Überprüfen der Isolation
Bestätigen Sie die Garantie mit dem A-A-B-Test der Probe. invoke_previous_response_isolation.py Führen Sie dies mit Ihrem bereitgestellten Agenten und zwei unterschiedlichen Benutzern aus (im Beispiel sind standardmäßig Alice und Bob voreingestellt):
- Erstellen Sie als Alice eine Antwort in einer freigegebenen Sitzung und erfassen Sie deren
id. - Erstellen Sie als Alice in derselben Sitzung eine zweite Antwort, wobei
previous_response_idauf dasidder ersten Antwort gesetzt ist, und erfassen Sie dessenid. - Als Bob senden Sie in derselben Sitzung eine Anfrage, bei der
previous_response_idauf Alices zweite Antwort gesetzt ist. Der Anruf schlägt fehl – Bob kann die Kette von Alice nicht fortsetzen.
Verwenden Sie zwei verschiedene Entra-Benutzer oder Objekt-IDs. Zwei Bezeichner, die sich zu derselben Identität auflösen, sind kein gültiger benutzerübergreifender Test.
Das Senden eines veralteten Isolationsheaders in einem Protokoll-2.0.0-Pfad führt zu einem Fehler, da dieses Modell durch den Plattformbenutzerkontext ersetzt wurde.
Verwandte Inhalte
- Isolieren Sie gehostete Agent-Sitzungen pro Benutzer für das standardmäßige Isolationsmodell pro Anrufer.
- Beispiel für Sitzungsmultiplexing für den vollständigen Middle-Tier-Sitzungspool, den Container-Handler und den Isolationstest.
- Beispiel für einen Notizagenten für einen Container, der benutzereigene Daten pro Sitzung persistent speichert (Python und C#).
- Kontingente und Grenzwerte für Foundry Agent Service für regionale Grenzwerte für gleichzeitige Sitzungen.
- Gehostete Agenten migrieren, um einen Container auf Protokoll 2.0.0 umzustellen.
- Laufzeitvertrag für gehostete Agents für die Plattformheader und Umgebungsvariablen, die ein Container erhält.