Microsoft Foundry

Microsoft Foundry 支持两种不同的上下文模式。 两者都使用 Foundry 托管的资源,但它们以不同的方式附加到代理,并解决不同的问题。

Pattern 代理框架机制 Behavior
文件搜索 RAG 提供程序托管的文件搜索工具 搜索应用程序在 Foundry 项目中显式上传和管理的文件和向量存储。
托管语义内存 FoundryMemoryProvider 上下文提供程序 从对话中提取事实和摘要,按范围存储它们,并在后续运行中检索相关记忆。

有关模型推理和服务托管的 Foundry 代理,请参阅 Microsoft Foundry 模型提供程序Microsoft Foundry 代理服务

使用文件搜索 RAG

当 Foundry 应为特选知识库拥有文档引入和矢量存储生命周期时,请使用此模式。 文件搜索是托管的工具,而不是上下文提供程序;请参阅工具行为的通用 文件搜索 指南。 当应用程序的真相源是Azure AI 搜索索引时,请使用Azure AI 搜索。

创建 Foundry 向量存储和代理

上传知识库文件,创建矢量存储、附加 FileSearchTool和创建版本控制 FoundryAgent

var endpoint = Environment.GetEnvironmentVariable("FOUNDRY_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("FOUNDRY_PROJECT_ENDPOINT is not set.");
var deploymentName = Environment.GetEnvironmentVariable("FOUNDRY_MODEL") ?? "gpt-5.4-mini";

// Create an AI Project client and get an OpenAI client that works with the foundry service.
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
AIProjectClient aiProjectClient = new(
    new Uri(endpoint),
    new DefaultAzureCredential());
OpenAIClient openAIClient = aiProjectClient.GetProjectOpenAIClient();

// Upload the file that contains the data to be used for RAG to the Foundry service.
OpenAIFileClient fileClient = openAIClient.GetOpenAIFileClient();
ClientResult<OpenAIFile> uploadResult = await fileClient.UploadFileAsync(
    filePath: "contoso-outdoors-knowledge-base.md",
    purpose: FileUploadPurpose.Assistants);

// Create a vector store in the Foundry service using the uploaded file.
VectorStoreClient vectorStoreClient = openAIClient.GetVectorStoreClient();
ClientResult<VectorStore> vectorStoreCreate = await vectorStoreClient.CreateVectorStoreAsync(options: new VectorStoreCreationOptions()
{
    Name = "contoso-outdoors-knowledge-base",
    FileIds = { uploadResult.Value.Id }
});

// Use the native OpenAI SDK FileSearchTool directly with the vector store ID.
#pragma warning disable OPENAI001
FileSearchTool fileSearchTool = new([vectorStoreCreate.Value.Id]);
#pragma warning restore OPENAI001

ProjectsAgentVersion agentVersion = await aiProjectClient.AgentAdministrationClient.CreateAgentVersionAsync(
    "AskContoso",
    new ProjectsAgentVersionCreationOptions(
        new DeclarativeAgentDefinition(model: deploymentName)
        {
            Instructions = "You are a helpful support specialist for Contoso Outdoors. Answer questions using the provided context and cite the source document when available.",
            Tools = { fileSearchTool }
        }));
FoundryAgent agent = aiProjectClient.AsAIAgent(agentVersion);

AgentSession session = await agent.CreateSessionAsync();

Console.WriteLine(">> Asking about returns\n");
Console.WriteLine(await agent.RunAsync("Hi! I need help understanding the return policy.", session));

Console.WriteLine("\n>> Asking about shipping\n");
Console.WriteLine(await agent.RunAsync("How long does standard shipping usually take?", session));

Console.WriteLine("\n>> Asking about product care\n");
Console.WriteLine(await agent.RunAsync("What is the best way to maintain the TrailRunner tent fabric?", session));

// Cleanup
await fileClient.DeleteFileAsync(uploadResult.Value.Id);
await vectorStoreClient.DeleteVectorStoreAsync(vectorStoreCreate.Value.Id);
await aiProjectClient.AgentAdministrationClient.DeleteAgentAsync(agent.Name);

为生产知识库重复使用永久性矢量存储,而不是为每个进程运行创建它们。

安装软件包

pip install agent-framework-foundry --pre

通过 Foundry 项目 OpenAI 客户端创建文件和矢量存储,然后将生成的文件搜索工具传递给代理。

async def create_vector_store(client: FoundryChatClient) -> tuple[str, str]:
    """Create a vector store with sample documents."""
    file = await client.client.files.create(
        file=("todays_weather.txt", b"The weather today is sunny with a high of 75F."), purpose="assistants"
    )
    vector_store = await client.client.vector_stores.create(
        name="knowledge_base",
        expires_after={"anchor": "last_active_at", "days": 1},
    )
    result = await client.client.vector_stores.files.create_and_poll(vector_store_id=vector_store.id, file_id=file.id)
    if result.last_error is not None:
        raise Exception(f"Vector store file processing failed with status: {result.last_error.message}")

    return file.id, vector_store.id


async def delete_vector_store(client: FoundryChatClient, file_id: str, vector_store_id: str) -> None:
    """Delete the vector store after using it."""
    with contextlib.suppress(Exception):
        await client.client.vector_stores.delete(vector_store_id=vector_store_id)
    with contextlib.suppress(Exception):
        await client.client.files.delete(file_id=file_id)


async def main() -> None:
    print("=== Foundry Chat Client with File Search Example ===\n")

    # Initialize the Foundry chat client
    # Make sure you're logged in via 'az login' before running this sample
    client = FoundryChatClient(credential=AzureCliCredential())

    file_id, vector_store_id = await create_vector_store(client)

    # Create file search tool using instance method
    file_search_tool = client.get_file_search_tool(vector_store_ids=[vector_store_id])

    agent = Agent(
        client=client,
        instructions="You are a helpful assistant that can search through files to find information.",
        tools=[file_search_tool],
    )

    query = "What is the weather today? Do a file search to find the answer."
    print(f"User: {query}")
    result = await agent.run(query)
    print(f"Agent: {result}\n")

    await delete_vector_store(client, file_id, vector_store_id)

注释

目前尚未为 Agent Framework Go 记录 Foundry 文件搜索集成。 有关最新的托管工具支持,请参阅 Agent Framework Go 存储库

添加托管语义内存

当代理应在会话之间召回持久用户或应用程序上下文时使用 FoundryMemoryProvider 。 Foundry 内存存储提取的事实和摘要与完整的对话脚本分开。

安装软件包

dotnet add package Microsoft.Agents.AI.Foundry --prerelease

使用稳定的作用域创建 FoundryMemoryProvider ,确保内存存储存在,并在依赖新提取的内存之前等待异步更新。

// Create an AIProjectClient for Foundry with Azure Identity authentication.
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
DefaultAzureCredential credential = new();
AIProjectClient projectClient = new(new Uri(foundryEndpoint), credential);

// Get the ChatClient from the AIProjectClient's OpenAI property using the deployment name.
// The stateInitializer can be used to customize the Foundry Memory scope per session and it will be called each time a session
// is encountered by the FoundryMemoryProvider that does not already have state stored on the session.
// If each session should have its own scope, you can create a new id per session via the stateInitializer, e.g.:
// new FoundryMemoryProvider(projectClient, memoryStoreName, stateInitializer: _ => new(new FoundryMemoryProviderScope(Guid.NewGuid().ToString())), ...)
// In our case we are storing memories scoped by user so that memories are retained across sessions.
FoundryMemoryProvider memoryProvider = new(
    projectClient,
    memoryStoreName,
    stateInitializer: _ => new(new FoundryMemoryProviderScope("sample-user-123")));

ChatClientAgent agent = projectClient.AsAIAgent(
    new ChatClientAgentOptions()
    {
        Name = "TravelAssistantWithFoundryMemory",
        ChatOptions = new()
        {
            ModelId = deploymentName,
            Instructions = "You are a friendly travel assistant. Use known memories about the user when responding, and do not invent details."
        },
        AIContextProviders = [memoryProvider]
    });

AgentSession session = await agent.CreateSessionAsync();

Console.WriteLine("\n>> Setting up Foundry Memory Store\n");

// Ensure the memory store exists (creates it with the specified models if needed).
await memoryProvider.EnsureMemoryStoreCreatedAsync(deploymentName, embeddingModelName, "Sample memory store for travel assistant");

// Clear any existing memories for this scope to demonstrate fresh behavior.
await memoryProvider.EnsureStoredMemoriesDeletedAsync(session);

Console.WriteLine(await agent.RunAsync("Hi there! My name is Taylor and I'm planning a hiking trip to Patagonia in November.", session));
Console.WriteLine(await agent.RunAsync("I'm travelling with my sister and we love finding scenic viewpoints.", session));

// Memory extraction in Microsoft Foundry is asynchronous and takes time to process.
// WhenUpdatesCompletedAsync polls all pending updates and waits for them to complete.
Console.WriteLine("\nWaiting for Foundry Memory to process updates...");
await memoryProvider.WhenUpdatesCompletedAsync();

Console.WriteLine("Updates completed.\n");

Console.WriteLine(await agent.RunAsync("What do you already know about my upcoming trip?", session));

Console.WriteLine("\n>> Serialize and deserialize the session to demonstrate persisted state\n");
JsonElement serializedSession = await agent.SerializeSessionAsync(session);
AgentSession restoredSession = await agent.DeserializeSessionAsync(serializedSession);
Console.WriteLine(await agent.RunAsync("Can you recap the personal details you remember?", restoredSession));

Console.WriteLine("\n>> Start a new session that shares the same Foundry Memory scope\n");

Console.WriteLine("\nWaiting for Foundry Memory to process updates...");
await memoryProvider.WhenUpdatesCompletedAsync();

AgentSession newSession = await agent.CreateSessionAsync();
Console.WriteLine(await agent.RunAsync("Summarize what you already know about me.", newSession));

安装软件包

pip install agent-framework-foundry --pre

创建内存存储, AIProjectClient然后附加到 FoundryMemoryProvider 代理。

async def main() -> None:
    endpoint = os.environ["FOUNDRY_PROJECT_ENDPOINT"]
    async with (
        AzureCliCredential() as credential,
        AIProjectClient(endpoint=endpoint, credential=credential) as project_client,
    ):
        # Generate a unique memory store name to avoid conflicts
        memory_store_name = f"agent_framework_memory_{datetime.now(timezone.utc).strftime('%Y%m%d')}"
        # Specify memory store options
        options = MemoryStoreDefaultOptions(
            chat_summary_enabled=False,
            user_profile_enabled=True,
            user_profile_details="Avoid irrelevant or sensitive data, such as age, financials, precise location, and credentials",
        )
        memory_store_definition = MemoryStoreDefaultDefinition(
            chat_model=os.environ["FOUNDRY_MODEL"],
            embedding_model=os.environ["AZURE_OPENAI_EMBEDDING_MODEL"],
            options=options,
        )
        print(f"Creating memory store '{memory_store_name}'...")
        try:
            # Create a memory store
            memory_store = await project_client.beta.memory_stores.create(
                name=memory_store_name,
                description="Memory store for Agent Framework with FoundryMemoryProvider",
                definition=memory_store_definition,
            )
        except Exception as e:
            print(f"Failed to create memory store: {e}")
            return

        print(f"Created memory store: {memory_store.name} ({memory_store.id})")
        print(f"Description: {memory_store.description}\n")
        print("==========================================")

        # Create the chat client
        client = FoundryChatClient(project_client=project_client)
        # Create the Foundry Memory context provider
        memory_provider = FoundryMemoryProvider(
            project_client=project_client,
            memory_store_name=memory_store.name,
            scope="user_123",  # Scope memories to a specific user, if not set, the session_id
            # will be used as scope, which means memories are only shared within the same session
            update_delay=0,  # Do not wait to update memories after each interaction (for demo purposes)
            # In production, consider setting a delay to batch updates and reduce costs
        )

        # Create an agent with the memory context provider
        async with Agent(
            name="MemoryAgent",
            client=client,
            instructions="""You are a helpful assistant that remembers past conversations.
                The memories from previous interactions are automatically provided to you.""",
            context_providers=[memory_provider, InMemoryHistoryProvider(load_messages=False)],
            default_options={"store": False},
        ) as agent:
            try:
                # note that we will use the service side storage, nor load messsages from the history provider,
                # but we include it to demonstrate that it can be used alongside the Foundry provider for other use cases.
                session = agent.create_session()

                # First interaction - establish some preferences
                print("=== First conversation ===")
                query1 = "I prefer dark roast coffee and I'm allergic to nuts"
                print(f"User: {query1}")
                result1 = await agent.run(query1, session=session)
                print(f"Agent: {result1}\n")

                # Wait for memories to be processed
                print("Waiting for memories to be stored...")
                await asyncio.sleep(8)

                # Second interaction - test memory recall
                print("=== Second conversation ===")
                query2 = "Can you recommend a coffee and snack for me?"
                print(f"User: {query2}")
                result2 = await agent.run(query2, session=session)
                print(f"Agent: {result2}\n")

                # Third interaction - continue the conversation
                print("=== Third conversation ===")
                query3 = "What do you remember about my preferences?"
                print(f"User: {query3}")
                result3 = await agent.run(query3, session=session)
                print(f"Agent: {result3}\n")

                print(f"Stored memories from: {memory_store.name} ({memory_store.id})")
                res = await project_client.beta.memory_stores.search_memories(name=memory_store.name, scope="user_123")
                for memory in res.memories:
                    print(f"Memory: {memory.memory_item.content}")

            except Exception as e:
                print(f"An error occurred: {e}")

            finally:
                await project_client.beta.memory_stores.delete(memory_store_name)

该示例禁用服务端和本地脚本加载,以便后面的响应演示语义内存,而不是聊天历史记录重播。

注释

Microsoft Foundry 内存集成目前不适用于 Agent Framework Go。 有关最新状态,请参阅 Agent Framework Go 存储库

生产注意事项

  • 为生产知识库重复使用永久性矢量存储。
  • 在选择范围之前,请使用应用程序拥有的稳定内存范围标识符并授权访问。
  • 在后续操作依赖于新写入的内存时等待异步提取。
  • 需要完整的对话记录时,请将确切的脚本保留在历史记录提供程序中。
  • 配置保留、区域和模型部署,以满足合规性要求。

后续步骤

更深入: