-
Notifications
You must be signed in to change notification settings - Fork 1.3k
[Projects] v2 update LRO poller for memory ops #36703
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
glharper
wants to merge
13
commits into
main
Choose a base branch
from
glharper/proj-mem-store-update
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
83c256b
[Projects] v2 update LRO poller for memory ops
glharper a224866
fix build
glharper e781cd4
format
glharper 400df57
unify model deployment name env var, gen mem tool sample
glharper cae1fc3
Merge branch 'main' into glharper/proj-mem-store-update
glharper d1b2cc5
Fix abort signal propagation in memory store update poller (#36707)
Copilot 53e4c06
Fix terminalUpdateStatuses to exclude failed status (#36709)
Copilot 722799d
Fix incomplete abort signal handling in memory store update poller (#…
Copilot 30b7cf6
fix bad merge
glharper fc9a6ba
rename poller file
glharper daca2d2
review feedback
glharper 2a6b473
simplify updating poller according to feedback
glharper feaf248
format
glharper File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
174 changes: 174 additions & 0 deletions
174
sdk/ai/ai-projects/samples-dev/agents/tools/agentMemorySearch.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,174 @@ | ||
| // Copyright (c) Microsoft Corporation. | ||
| // Licensed under the MIT License. | ||
|
|
||
| /** | ||
| * This sample demonstrates how to add conversational memory to an agent by using the | ||
| * Memory Search tool. The agent stores memories in a memory store and can recall them | ||
| * in later conversations. | ||
| * | ||
| * @summary Create an agent with Memory Search, capture memories from a conversation, | ||
| * and retrieve them in a new conversation. | ||
| * | ||
| * @azsdk-weight 100 | ||
| */ | ||
|
|
||
| import { DefaultAzureCredential } from "@azure/identity"; | ||
| import { | ||
| AIProjectClient, | ||
| MemoryStoreDefaultDefinition, | ||
| MemoryStoreDefaultOptions, | ||
| MemorySearchTool, | ||
| } from "@azure/ai-projects"; | ||
| import "dotenv/config"; | ||
|
|
||
| const projectEndpoint = process.env["AZURE_AI_PROJECT_ENDPOINT"] || "<project endpoint>"; | ||
| const agentModelDeployment = | ||
| process.env["MODEL_DEPLOYMENT_NAME"] || "<agent model deployment name>"; | ||
| const chatModelDeployment = | ||
| process.env["AZURE_AI_CHAT_MODEL_DEPLOYMENT_NAME"] || "<memory chat model deployment name>"; | ||
| const embeddingModelDeployment = | ||
| process.env["AZURE_AI_EMBEDDING_MODEL_DEPLOYMENT_NAME"] || | ||
| "<memory embedding model deployment name>"; | ||
|
|
||
| const memoryStoreName = "my_memory_store_123"; | ||
| const scope = "user_123"; | ||
|
|
||
| function delay(ms: number): Promise<void> { | ||
| return new Promise((resolve) => setTimeout(resolve, ms)); | ||
| } | ||
|
|
||
| export async function main(): Promise<void> { | ||
| const project = new AIProjectClient(projectEndpoint, new DefaultAzureCredential()); | ||
| const openAIClient = await project.getOpenAIClient(); | ||
|
|
||
| let conversationId: string | undefined; | ||
| let followUpConversationId: string | undefined; | ||
| let agentVersion: | ||
| | { | ||
| name: string; | ||
| version: string; | ||
| } | ||
| | undefined; | ||
|
|
||
| try { | ||
| // Clean up an existing memory store if it already exists | ||
| try { | ||
| await project.memoryStores.delete(memoryStoreName); | ||
| console.log(`Memory store '${memoryStoreName}' deleted`); | ||
| } catch (error: any) { | ||
| if (error?.statusCode !== 404) { | ||
| throw error; | ||
| } | ||
| } | ||
|
|
||
| // Create a memory store with chat and embedding models | ||
| const memoryStore = await project.memoryStores.create( | ||
| memoryStoreName, | ||
| { | ||
| kind: "default", | ||
| chat_model: chatModelDeployment, | ||
| embedding_model: embeddingModelDeployment, | ||
| options: { | ||
| user_profile_enabled: true, | ||
| chat_summary_enabled: true, | ||
| } satisfies MemoryStoreDefaultOptions, | ||
| } satisfies MemoryStoreDefaultDefinition, | ||
| { | ||
| description: "Memory store for agent conversations", | ||
| }, | ||
| ); | ||
| const chatModelUsed = | ||
| "chat_model" in memoryStore.definition | ||
| ? memoryStore.definition.chat_model | ||
| : chatModelDeployment; | ||
| console.log( | ||
| `Created memory store: ${memoryStore.name} (${memoryStore.id}) using chat model '${chatModelUsed}'`, | ||
| ); | ||
|
|
||
| // Configure Memory Search tool to attach to the agent | ||
| const memorySearchTool: MemorySearchTool = { | ||
| type: "memory_search", | ||
| memory_store_name: memoryStore.name, | ||
| scope, | ||
| update_delay: 1, // wait briefly after conversation inactivity before updating memories | ||
| }; | ||
|
|
||
| // Create an agent that will use the Memory Search tool | ||
| const agent = await project.agents.createVersion("MemorySearchAgent", { | ||
| kind: "prompt", | ||
| model: agentModelDeployment, | ||
| instructions: | ||
| "You are a helpful assistant that remembers user preferences using the memory search tool.", | ||
| tools: [memorySearchTool], | ||
| }); | ||
| agentVersion = { | ||
| name: agent.name, | ||
| version: agent.version, | ||
| }; | ||
| console.log(`Agent created (id: ${agent.id}, name: ${agent.name}, version: ${agent.version})`); | ||
|
|
||
| // Start a conversation and provide details the agent should remember | ||
| const conversation = await openAIClient.conversations.create(); | ||
| conversationId = conversation.id; | ||
| console.log(`Conversation started (${conversation.id}). Sending a message to seed memories...`); | ||
|
|
||
| const firstResponse = await openAIClient.responses.create( | ||
| { | ||
| input: "I prefer dark roast coffee and usually drink it in the morning.", | ||
| conversation: conversation.id, | ||
| }, | ||
| { | ||
| body: { agent: { name: agent.name, type: "agent_reference" } }, | ||
| }, | ||
| ); | ||
| console.log(`Initial response: ${firstResponse.output_text}`); | ||
|
|
||
| // Allow time for the memory store to update from this conversation | ||
| console.log("Waiting for the memory store to capture the new memory..."); | ||
| await delay(60000); | ||
|
|
||
| // Create a follow-up conversation and ask the agent to recall the stored memory | ||
| const followUpConversation = await openAIClient.conversations.create(); | ||
| followUpConversationId = followUpConversation.id; | ||
| console.log(`Follow-up conversation started (${followUpConversation.id}).`); | ||
|
|
||
| const followUpResponse = await openAIClient.responses.create( | ||
| { | ||
| input: "Can you remind me of my usual coffee order?", | ||
| conversation: followUpConversation.id, | ||
| }, | ||
| { | ||
| body: { agent: { name: agent.name, type: "agent_reference" } }, | ||
| }, | ||
| ); | ||
| console.log(`Follow-up response: ${followUpResponse.output_text}`); | ||
| } finally { | ||
| console.log("\nCleaning up resources..."); | ||
| if (conversationId) { | ||
| await openAIClient.conversations.delete(conversationId); | ||
| console.log(`Conversation ${conversationId} deleted`); | ||
| } | ||
| if (followUpConversationId) { | ||
| await openAIClient.conversations.delete(followUpConversationId); | ||
| console.log(`Conversation ${followUpConversationId} deleted`); | ||
| } | ||
| if (agentVersion) { | ||
| await project.agents.deleteVersion(agentVersion.name, agentVersion.version); | ||
| console.log("Agent deleted"); | ||
| } | ||
| try { | ||
| await project.memoryStores.delete(memoryStoreName); | ||
| console.log("Memory store deleted"); | ||
| } catch (error: any) { | ||
| if (error?.statusCode !== 404) { | ||
| throw error; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| console.log("\nMemory Search agent sample completed!"); | ||
| } | ||
|
|
||
| main().catch((err) => { | ||
| console.error("The sample encountered an error:", err); | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we override existing status property instead of defining a new updateStatus?
(Surprised by OperationState_2 name)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updateId and status are both required, if that is consistent with OperationState_2 design.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason for the OperationState name collision is that another "OperationState" is apparently being emitted from our TypeSpec, and that local OperationState roughly corresponds to the OperationStatus enum in core-lro/poller.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are the responses from the service constrained to the OperationStatus strings? I'm seeing "queued" and "superseded" as possible return statuses, but those don't exist in the OperationStatus enums here