mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Python: Fix broken samples and add missing READMEs (#5038)
* Python: Fix broken samples and add missing READMEs - simple_context_provider: move instructions kwarg into options dict - suspend_resume_session: use OpenAIChatCompletionClient for in-memory demo - foundry_chat_client_with_hosted_mcp: move store kwarg into options dict - Add README.md for context_providers and conversations sample folders Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Python: Fix additional sample issues in context_providers - mem0_basic: send preferences query before sleep so Mem0 can learn them, print result from new session recall - mem0_sessions: add session for multi-turn conversation in agent-scoped example, remove user_id from agent-scoped provider (Mem0 API stores memories without user_id when agent_id is provided), use single message for storing preferences - redis_basics: print retrieved context messages instead of raw object - redis_sessions: add missing load_dotenv() call - redis_basics/redis_sessions: fix docstrings referencing wrong client type - azure_redis_conversation: replace duplicate copyright with load_dotenv() Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Python: Fix broken link in declarative README openai_responses_agent.py was renamed to openai_agent.py Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
Unverified
parent
15e435b472
commit
6f6ee61834
@@ -0,0 +1,28 @@
|
||||
# Context Provider Samples
|
||||
|
||||
These samples demonstrate how to use context providers to enrich agent conversations with external knowledge — from custom logic to Azure AI Search (RAG) and memory services.
|
||||
|
||||
## Samples
|
||||
|
||||
| File / Folder | Description |
|
||||
|---------------|-------------|
|
||||
| [`simple_context_provider.py`](simple_context_provider.py) | Implement a custom context provider by extending `BaseContextProvider` to extract and inject structured user information across turns. |
|
||||
| [`azure_ai_foundry_memory.py`](azure_ai_foundry_memory.py) | Use `FoundryMemoryProvider` to add semantic memory — automatically retrieves, searches, and stores memories via Azure AI Foundry. |
|
||||
| [`azure_ai_search/`](azure_ai_search/) | Retrieval Augmented Generation (RAG) with Azure AI Search in semantic and agentic modes. See its own [README](azure_ai_search/README.md). |
|
||||
| [`mem0/`](mem0/) | Memory-powered context using the Mem0 integration (open-source and managed). See its own [README](mem0/README.md). |
|
||||
| [`redis/`](redis/) | Redis-backed context providers for conversation memory and sessions. See its own [README](redis/README.md). |
|
||||
|
||||
## Prerequisites
|
||||
|
||||
**For `simple_context_provider.py`:**
|
||||
- `FOUNDRY_PROJECT_ENDPOINT`: Your Azure AI Foundry project endpoint
|
||||
- `FOUNDRY_MODEL`: Model deployment name
|
||||
- Azure CLI authentication (`az login`)
|
||||
|
||||
**For `azure_ai_foundry_memory.py`:**
|
||||
- `FOUNDRY_PROJECT_ENDPOINT`: Your Azure AI Foundry project endpoint
|
||||
- `FOUNDRY_MODEL`: Chat/responses model deployment name
|
||||
- `AZURE_OPENAI_EMBEDDING_DEPLOYMENT_NAME`: Embedding model deployment name (e.g., `text-embedding-ada-002`)
|
||||
- Azure CLI authentication (`az login`)
|
||||
|
||||
See each subfolder's README for provider-specific prerequisites.
|
||||
@@ -57,12 +57,16 @@ async def main() -> None:
|
||||
# Now tell the agent the company code and the report format that you want to use
|
||||
# and it should be able to invoke the tool and return the report.
|
||||
query = "I always work with CNTS and I always want a detailed report format. Please remember and retrieve it."
|
||||
print(f"User: {query}")
|
||||
result = await agent.run(query)
|
||||
print(f"Agent: {result}\n")
|
||||
|
||||
# Mem0 processes and indexes memories asynchronously.
|
||||
# Wait for memories to be indexed before querying in a new thread.
|
||||
# In production, consider implementing retry logic or using Mem0's
|
||||
# eventual consistency handling instead of a fixed delay.
|
||||
print("Waiting for memories to be processed...")
|
||||
await asyncio.sleep(12) # Empirically determined delay for Mem0 indexing
|
||||
await asyncio.sleep(15) # Empirically determined delay for Mem0 indexing
|
||||
print("\nRequest within a new session:")
|
||||
# Create a new session for the agent.
|
||||
# The new session has no context of the previous conversation.
|
||||
@@ -70,7 +74,10 @@ async def main() -> None:
|
||||
# Since we have the mem0 component in the session, the agent should be able to
|
||||
# retrieve the company report without asking for clarification, as it will
|
||||
# be able to remember the user preferences from Mem0 component.
|
||||
query = "Please retrieve my company report"
|
||||
print(f"User: {query}")
|
||||
result = await agent.run(query, session=session)
|
||||
print(f"Agent: {result}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -71,8 +71,6 @@ async def example_agent_scoped_memory() -> None:
|
||||
print("2. Agent-Scoped Memory Example:")
|
||||
print("-" * 40)
|
||||
|
||||
user_id = "user123"
|
||||
|
||||
async with (
|
||||
AzureCliCredential() as credential,
|
||||
Agent(
|
||||
@@ -83,34 +81,23 @@ async def example_agent_scoped_memory() -> None:
|
||||
context_providers=[
|
||||
Mem0ContextProvider(
|
||||
source_id="mem0",
|
||||
user_id=user_id,
|
||||
agent_id="scoped_assistant",
|
||||
)
|
||||
],
|
||||
) as scoped_agent,
|
||||
):
|
||||
# Store some information
|
||||
query = "Remember that for this conversation, I'm working on a Python project about data analysis."
|
||||
query = (
|
||||
"Remember that I'm working on a Python project about data analysis "
|
||||
"and I prefer using pandas and matplotlib."
|
||||
)
|
||||
print(f"User: {query}")
|
||||
result = await scoped_agent.run(query)
|
||||
print(f"Agent: {result}\n")
|
||||
|
||||
# Test memory retrieval
|
||||
query = "What project am I working on?"
|
||||
print(f"User: {query}")
|
||||
result = await scoped_agent.run(query)
|
||||
print(f"Agent: {result}\n")
|
||||
|
||||
# Store more information
|
||||
query = "Also remember that I prefer using pandas and matplotlib for this project."
|
||||
print(f"User: {query}")
|
||||
result = await scoped_agent.run(query)
|
||||
print(f"Agent: {result}\n")
|
||||
|
||||
# Test comprehensive memory retrieval
|
||||
new_session = scoped_agent.create_session()
|
||||
query = "What do you know about my current project and preferences?"
|
||||
print(f"User: {query}")
|
||||
result = await scoped_agent.run(query)
|
||||
print(f"User (new session): {query}")
|
||||
result = await scoped_agent.run(query, session=new_session)
|
||||
print(f"Agent: {result}\n")
|
||||
|
||||
|
||||
|
||||
@@ -30,9 +30,10 @@ from agent_framework.foundry import FoundryChatClient
|
||||
from agent_framework.redis import RedisHistoryProvider
|
||||
from azure.identity import AzureCliCredential
|
||||
from azure.identity.aio import AzureCliCredential as AsyncAzureCliCredential
|
||||
from dotenv import load_dotenv
|
||||
from redis.credentials import CredentialProvider
|
||||
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
load_dotenv()
|
||||
|
||||
|
||||
class AzureCredentialProvider(CredentialProvider):
|
||||
|
||||
@@ -100,7 +100,7 @@ def search_flights(origin_airport_code: str, destination_airport_code: str, deta
|
||||
|
||||
|
||||
def create_chat_client() -> FoundryChatClient:
|
||||
"""Create an Azure OpenAI Responses client using a Foundry project endpoint."""
|
||||
"""Create a FoundryChatClient using a Foundry project endpoint."""
|
||||
return FoundryChatClient(
|
||||
project_endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"],
|
||||
model=os.environ["FOUNDRY_MODEL"],
|
||||
|
||||
@@ -34,10 +34,12 @@ from agent_framework import Agent
|
||||
from agent_framework.foundry import FoundryChatClient
|
||||
from agent_framework.redis import RedisContextProvider
|
||||
from azure.identity import AzureCliCredential
|
||||
from dotenv import load_dotenv
|
||||
from redisvl.extensions.cache.embeddings import EmbeddingsCache
|
||||
from redisvl.utils.vectorize import OpenAITextVectorizer
|
||||
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
# Load environment variables from .env file
|
||||
load_dotenv()
|
||||
|
||||
|
||||
# Default Redis URL for local Redis Stack.
|
||||
@@ -48,7 +50,7 @@ REDIS_URL = os.getenv("REDIS_URL", "redis://localhost:6379")
|
||||
# Please set OPENAI_API_KEY to use the OpenAI vectorizer.
|
||||
# For chat responses, also set FOUNDRY_PROJECT_ENDPOINT and FOUNDRY_MODEL.
|
||||
def create_chat_client() -> FoundryChatClient:
|
||||
"""Create an Azure OpenAI Responses client using a Foundry project endpoint."""
|
||||
"""Create a FoundryChatClient using a Foundry project endpoint."""
|
||||
return FoundryChatClient(
|
||||
project_endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"],
|
||||
model=os.environ["FOUNDRY_MODEL"],
|
||||
|
||||
@@ -50,9 +50,11 @@ class UserInfoMemory(ContextProvider):
|
||||
# Use the chat client to extract structured information
|
||||
result = await self._chat_client.get_response(
|
||||
messages=request_messages, # type: ignore
|
||||
instructions="Extract the user's name and age from the message if present. "
|
||||
"If not present return nulls.",
|
||||
options={"response_format": UserInfo},
|
||||
options={
|
||||
"instructions": "Extract the user's name and age from the message if present. "
|
||||
"If not present return nulls.",
|
||||
"response_format": UserInfo,
|
||||
},
|
||||
)
|
||||
|
||||
# Update user info with extracted data
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
# Conversation & Session Management Samples
|
||||
|
||||
These samples demonstrate different approaches to managing conversation history and session state in Agent Framework.
|
||||
|
||||
## Samples
|
||||
|
||||
| File | Description |
|
||||
|------|-------------|
|
||||
| [`suspend_resume_session.py`](suspend_resume_session.py) | Suspend and resume conversation sessions, comparing service-managed sessions (Azure AI Foundry) with in-memory sessions (OpenAI). |
|
||||
| [`custom_history_provider.py`](custom_history_provider.py) | Implement a custom history provider by extending `BaseHistoryProvider`, enabling conversation persistence in your preferred storage backend. |
|
||||
| [`redis_history_provider.py`](redis_history_provider.py) | Use Redis as a history provider for persistent conversation history storage across sessions. |
|
||||
|
||||
## Prerequisites
|
||||
|
||||
**For `suspend_resume_session.py`:**
|
||||
- `FOUNDRY_PROJECT_ENDPOINT`: Your Azure AI Foundry project endpoint (service-managed session)
|
||||
- `FOUNDRY_MODEL`: The Foundry model deployment name
|
||||
- `OPENAI_API_KEY`: Your OpenAI API key (in-memory session)
|
||||
- Azure CLI authentication (`az login`)
|
||||
|
||||
**For `custom_history_provider.py`:**
|
||||
- `OPENAI_API_KEY`: Your OpenAI API key
|
||||
|
||||
**For `redis_history_provider.py`:**
|
||||
- `OPENAI_API_KEY`: Your OpenAI API key
|
||||
- A running Redis server — default URL is `redis://localhost:6379`
|
||||
- Override via the `REDIS_URL` environment variable for remote or authenticated instances
|
||||
- Quickstart with Docker: `docker run -d --name redis-stack -p 6379:6379 redis/redis-stack-server:latest`
|
||||
@@ -4,6 +4,7 @@ import asyncio
|
||||
|
||||
from agent_framework import Agent, AgentSession
|
||||
from agent_framework.foundry import FoundryChatClient
|
||||
from agent_framework.openai import OpenAIChatCompletionClient
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
from dotenv import load_dotenv
|
||||
|
||||
@@ -62,7 +63,7 @@ async def suspend_resume_in_memory_session() -> None:
|
||||
# OpenAI Chat Client is used as an example here,
|
||||
# other chat clients can be used as well.
|
||||
agent = Agent(
|
||||
client=FoundryChatClient(),
|
||||
client=OpenAIChatCompletionClient(),
|
||||
name="MemoryBot",
|
||||
instructions="You are a helpful assistant that remembers our conversation.",
|
||||
)
|
||||
|
||||
@@ -68,7 +68,7 @@ Illustrates a basic agent using Azure OpenAI with structured responses.
|
||||
|
||||
**Key concepts**: Azure OpenAI integration, credential management, structured outputs
|
||||
|
||||
### 5. **OpenAI Responses Agent** ([`openai_responses_agent.py`](./openai_responses_agent.py))
|
||||
### 5. **OpenAI Responses Agent** ([`openai_agent.py`](./openai_agent.py))
|
||||
|
||||
Demonstrates the simplest possible agent using OpenAI directly.
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ async def handle_approvals_with_session(query: str, agent: "SupportsAgentRun", s
|
||||
"""Here we let the session deal with the previous responses, and we just rerun with the approval."""
|
||||
from agent_framework import Message
|
||||
|
||||
result = await agent.run(query, session=session, store=True)
|
||||
result = await agent.run(query, session=session, options={"store": True})
|
||||
while len(result.user_input_requests) > 0:
|
||||
new_input: list[Any] = []
|
||||
for user_input_needed in result.user_input_requests:
|
||||
@@ -66,7 +66,7 @@ async def handle_approvals_with_session(query: str, agent: "SupportsAgentRun", s
|
||||
contents=[user_input_needed.to_function_approval_response(user_approval.lower() == "y")],
|
||||
)
|
||||
)
|
||||
result = await agent.run(new_input, session=session, store=True)
|
||||
result = await agent.run(new_input, session=session, options={"store": True})
|
||||
return result
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user