mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Done: Foundry Memory
This commit is contained in:
+2
-5
@@ -1,9 +1,6 @@
|
||||
FOUNDRY_PROJECT_ENDPOINT="..."
|
||||
AZURE_AI_MODEL_DEPLOYMENT_NAME="..."
|
||||
# Embedding model deployment (only needed by provision_memory_store.py).
|
||||
AZURE_OPENAI_EMBEDDING_MODEL="text-embedding-3-small"
|
||||
AZURE_AI_EMBEDDING_MODEL_DEPLOYMENT_NAME="text-embedding-3-small"
|
||||
# Name of the Foundry Memory Store the agent should read/write to.
|
||||
FOUNDRY_MEMORY_STORE_NAME="agent_framework_memory"
|
||||
# Optional scope (e.g., user id) used to isolate memories. Falls back to the
|
||||
# per-session id when unset, which limits memories to a single session.
|
||||
FOUNDRY_MEMORY_SCOPE="user_123"
|
||||
MEMORY_STORE_NAME="agent_framework_memory"
|
||||
+11
-15
@@ -44,8 +44,8 @@ From this directory, with the venv activated and `az login` done:
|
||||
```bash
|
||||
export FOUNDRY_PROJECT_ENDPOINT="https://<account>.services.ai.azure.com/api/projects/<project>"
|
||||
export AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4.1-mini"
|
||||
export AZURE_OPENAI_EMBEDDING_MODEL="text-embedding-3-small"
|
||||
export FOUNDRY_MEMORY_STORE_NAME="agent_framework_memory"
|
||||
export AZURE_AI_EMBEDDING_MODEL_DEPLOYMENT_NAME="text-embedding-3-small"
|
||||
export MEMORY_STORE_NAME="agent_framework_memory"
|
||||
python provision_memory_store.py
|
||||
```
|
||||
|
||||
@@ -54,8 +54,8 @@ Or in PowerShell:
|
||||
```powershell
|
||||
$env:FOUNDRY_PROJECT_ENDPOINT="https://<account>.services.ai.azure.com/api/projects/<project>"
|
||||
$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4.1-mini"
|
||||
$env:AZURE_OPENAI_EMBEDDING_MODEL="text-embedding-3-small"
|
||||
$env:FOUNDRY_MEMORY_STORE_NAME="agent_framework_memory"
|
||||
$env:AZURE_AI_EMBEDDING_MODEL_DEPLOYMENT_NAME="text-embedding-3-small"
|
||||
$env:MEMORY_STORE_NAME="agent_framework_memory"
|
||||
python provision_memory_store.py
|
||||
```
|
||||
|
||||
@@ -75,16 +75,13 @@ Follow the instructions in the [Running the Agent Host Locally](../../README.md#
|
||||
In addition to the standard environment variables, this sample requires:
|
||||
|
||||
```bash
|
||||
export FOUNDRY_MEMORY_STORE_NAME="agent_framework_memory"
|
||||
# Optional — defaults to "user_123" in main.py if unset.
|
||||
export FOUNDRY_MEMORY_SCOPE="user_123"
|
||||
export MEMORY_STORE_NAME="agent_framework_memory"
|
||||
```
|
||||
|
||||
Or in PowerShell:
|
||||
|
||||
```powershell
|
||||
$env:FOUNDRY_MEMORY_STORE_NAME="agent_framework_memory"
|
||||
$env:FOUNDRY_MEMORY_SCOPE="user_123"
|
||||
$env:MEMORY_STORE_NAME="agent_framework_memory"
|
||||
```
|
||||
|
||||
You can also place these in a `.env` file next to `main.py` — see [`.env.example`](.env.example).
|
||||
@@ -93,7 +90,9 @@ You can also place these in a `.env` file next to `main.py` — see [`.env.examp
|
||||
|
||||
> Depending on how you run the agent host, you can invoke the agent using `curl` (`Invoke-WebRequest` in PowerShell) or `azd`. Please refer to the [parent README](../../README.md) for more details.
|
||||
|
||||
Send a POST request to the server with a JSON body containing an `"input"` field to interact with the agent. The first request seeds a memory; subsequent requests (especially in new sessions) should be able to recall it because memories are scoped to `FOUNDRY_MEMORY_SCOPE`, not to a particular session.
|
||||
Send a POST request to the server with a JSON body containing an `"input"` field to interact with the agent. The first request seeds a memory; subsequent requests (especially in new sessions) should be able to recall it because memories are persisted across Foundry Hosted Agents sessions.
|
||||
|
||||
> In this sample, the memory is scoped to the user by specifying `scope="{{$userId}}"`, thus memories are isolated across different users but shared across different sessions from the same user.
|
||||
|
||||
```bash
|
||||
# 1. Tell the agent something to remember.
|
||||
@@ -108,17 +107,14 @@ curl -X POST http://localhost:8088/responses -H "Content-Type: application/json"
|
||||
-d '{"input": "What do you remember about my preferences?"}'
|
||||
```
|
||||
|
||||
The agent's answers to the follow-up turns should reflect the preferences shared in the first turn, even though `default_options={"store": False}` is set (so the Responses service is not persisting conversation history) — the recall is coming exclusively from the Foundry Memory Store.
|
||||
|
||||
## Deploying the Agent to Foundry
|
||||
|
||||
To host the agent on Foundry, follow the instructions in the [Deploying the Agent to Foundry](../../README.md#deploying-the-agent-to-foundry) section of the README in the parent directory.
|
||||
|
||||
When deploying, make sure `FOUNDRY_MEMORY_STORE_NAME` and `FOUNDRY_MEMORY_SCOPE` are set in your `azd` environment so they get injected into the hosted container per [`agent.manifest.yaml`](agent.manifest.yaml):
|
||||
When deploying, make sure `MEMORY_STORE_NAME` and `FOUNDRY_MEMORY_SCOPE` are set in your `azd` environment so they get injected into the hosted container per [`agent.manifest.yaml`](agent.manifest.yaml):
|
||||
|
||||
```bash
|
||||
azd env set FOUNDRY_MEMORY_STORE_NAME "agent_framework_memory"
|
||||
azd env set FOUNDRY_MEMORY_SCOPE "user_123"
|
||||
azd env set MEMORY_STORE_NAME "agent_framework_memory"
|
||||
```
|
||||
|
||||
If these are not set, running `azd ai agent init -m <agent-manifest.yaml>` will prompt you to enter them interactively.
|
||||
|
||||
+3
-8
@@ -20,18 +20,13 @@ template:
|
||||
environment_variables:
|
||||
- name: AZURE_AI_MODEL_DEPLOYMENT_NAME
|
||||
value: "{{AZURE_AI_MODEL_DEPLOYMENT_NAME}}"
|
||||
- name: FOUNDRY_MEMORY_STORE_NAME
|
||||
value: "{{FOUNDRY_MEMORY_STORE_NAME}}"
|
||||
- name: FOUNDRY_MEMORY_SCOPE
|
||||
value: "{{FOUNDRY_MEMORY_SCOPE}}"
|
||||
- name: MEMORY_STORE_NAME
|
||||
value: "{{MEMORY_STORE_NAME}}"
|
||||
parameters:
|
||||
properties:
|
||||
- name: FOUNDRY_MEMORY_STORE_NAME
|
||||
- name: MEMORY_STORE_NAME
|
||||
secret: false
|
||||
description: The name of the pre-provisioned Foundry Memory Store the agent will use (e.g., agent_framework_memory)
|
||||
- name: FOUNDRY_MEMORY_SCOPE
|
||||
secret: false
|
||||
description: Scope (e.g., user id) used to isolate memories within the store (e.g., user_123)
|
||||
resources:
|
||||
- kind: model
|
||||
id: gpt-4.1-mini
|
||||
|
||||
+2
-4
@@ -10,7 +10,5 @@ resources:
|
||||
environment_variables:
|
||||
- name: AZURE_AI_MODEL_DEPLOYMENT_NAME
|
||||
value: ${AZURE_AI_MODEL_DEPLOYMENT_NAME}
|
||||
- name: FOUNDRY_MEMORY_STORE_NAME
|
||||
value: ${FOUNDRY_MEMORY_STORE_NAME}
|
||||
- name: FOUNDRY_MEMORY_SCOPE
|
||||
value: ${FOUNDRY_MEMORY_SCOPE}
|
||||
- name: MEMORY_STORE_NAME
|
||||
value: ${MEMORY_STORE_NAME}
|
||||
|
||||
+7
-10
@@ -6,7 +6,7 @@ This agent uses :class:`FoundryMemoryProvider` to give an otherwise stateless
|
||||
hosted agent persistent, semantic memory backed by an Azure AI Foundry
|
||||
Memory Store. The store itself is provisioned once via
|
||||
``provision_memory_store.py`` and its name is passed in through the
|
||||
``FOUNDRY_MEMORY_STORE_NAME`` environment variable.
|
||||
``MEMORY_STORE_NAME`` environment variable.
|
||||
|
||||
Unlike the standalone ``azure_ai_foundry_memory.py`` sample, here we construct
|
||||
the :class:`FoundryChatClient` first and then reuse its underlying
|
||||
@@ -41,15 +41,12 @@ async def main() -> None:
|
||||
# constructing a second one for the memory provider.
|
||||
memory_provider = FoundryMemoryProvider(
|
||||
project_client=client.project_client,
|
||||
memory_store_name=os.environ["FOUNDRY_MEMORY_STORE_NAME"],
|
||||
# Scope namespaces memories (e.g., per end-user). When unset, the
|
||||
# provider falls back to the session id, which limits memories to a
|
||||
# single session.
|
||||
scope=os.environ.get("FOUNDRY_MEMORY_SCOPE", "user_123"),
|
||||
# In production, leave update_delay at its default to batch updates and
|
||||
# reduce cost. We use 0 here so memories are written immediately, which
|
||||
# makes the sample easier to demo.
|
||||
update_delay=0,
|
||||
memory_store_name=os.environ["MEMORY_STORE_NAME"],
|
||||
# Scope memories by user id, so each user that interacts with the agent
|
||||
# has their own isolated memories in the store (assuming those users are
|
||||
# granted access). `{{userId}}` is a special placeholder that the hosting
|
||||
# infrastructure will replace with the actual user id at runtime.
|
||||
scope="{{$userId}}",
|
||||
)
|
||||
|
||||
agent = Agent(
|
||||
|
||||
+21
-9
@@ -2,7 +2,7 @@
|
||||
|
||||
"""Provision the Azure AI Foundry Memory Store used by this sample.
|
||||
|
||||
Creates the memory store named by ``FOUNDRY_MEMORY_STORE_NAME`` if it does not
|
||||
Creates the memory store named by ``MEMORY_STORE_NAME`` if it does not
|
||||
already exist. The store is configured with the user-profile capability so the
|
||||
agent can remember stable facts about a user across sessions; chat-summary is
|
||||
disabled to keep the demo focused on durable preferences. Safe to re-run: if a
|
||||
@@ -14,10 +14,10 @@ Usage (from this directory, with the venv activated and ``az login`` done):
|
||||
|
||||
Required env vars (also read from a local ``.env`` file if present):
|
||||
|
||||
FOUNDRY_PROJECT_ENDPOINT e.g. https://<account>.services.ai.azure.com/api/projects/<project>
|
||||
AZURE_AI_MODEL_DEPLOYMENT_NAME Chat model deployment used by the memory store
|
||||
AZURE_OPENAI_EMBEDDING_MODEL Embedding model deployment used by the memory store
|
||||
FOUNDRY_MEMORY_STORE_NAME Name of the memory store to create
|
||||
FOUNDRY_PROJECT_ENDPOINT e.g. https://<account>.services.ai.azure.com/api/projects/<project>
|
||||
AZURE_AI_MODEL_DEPLOYMENT_NAME Chat model deployment used by the memory store
|
||||
AZURE_AI_EMBEDDING_MODEL_DEPLOYMENT_NAME Embedding model deployment used by the memory store
|
||||
MEMORY_STORE_NAME Name of the memory store to create
|
||||
|
||||
Your identity needs ``Azure AI User`` on the Foundry project scope.
|
||||
"""
|
||||
@@ -34,14 +34,14 @@ from azure.core.exceptions import ResourceNotFoundError
|
||||
from azure.identity.aio import DefaultAzureCredential
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
load_dotenv()
|
||||
|
||||
endpoint = os.environ["FOUNDRY_PROJECT_ENDPOINT"]
|
||||
memory_store_name = os.environ["FOUNDRY_MEMORY_STORE_NAME"]
|
||||
memory_store_name = os.environ["MEMORY_STORE_NAME"]
|
||||
chat_model = os.environ["AZURE_AI_MODEL_DEPLOYMENT_NAME"]
|
||||
embedding_model = os.environ["AZURE_OPENAI_EMBEDDING_MODEL"]
|
||||
embedding_model = os.environ["AZURE_AI_EMBEDDING_MODEL_DEPLOYMENT_NAME"]
|
||||
|
||||
async with (
|
||||
DefaultAzureCredential() as credential,
|
||||
@@ -73,6 +73,18 @@ async def main() -> None:
|
||||
)
|
||||
print(f"Created memory store '{created.name}' (id={created.id}).")
|
||||
|
||||
# Verify the store actually exists on the service by reading it back.
|
||||
# ``create`` returns the requested definition, but a follow-up ``get``
|
||||
# confirms the store is persisted and reachable for the agent at runtime.
|
||||
try:
|
||||
verified = await project.beta.memory_stores.get(name=memory_store_name)
|
||||
except ResourceNotFoundError as exc:
|
||||
raise RuntimeError(
|
||||
f"Memory store '{memory_store_name}' was not found after creation; "
|
||||
"the service may not have persisted it."
|
||||
) from exc
|
||||
print(f"Verified memory store '{verified.name}' is available on the service (id={verified.id}).")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
|
||||
Reference in New Issue
Block a user