Skip to content

Commit 83c256b

Browse files
committed
[Projects] v2 update LRO poller for memory ops
1 parent 0a36a6c commit 83c256b

File tree

9 files changed

+476
-42
lines changed

9 files changed

+476
-42
lines changed

sdk/ai/ai-projects/review/ai-projects-node.api.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1841,7 +1841,7 @@ export interface MemoryStoresOperations {
18411841
list: (options?: MemoryStoresListMemoryStoresOptionalParams) => PagedAsyncIterableIterator<MemoryStore>;
18421842
searchMemories: (name: string, scope: string, options?: MemoryStoresSearchMemoriesOptionalParams) => Promise<MemoryStoreSearchResponse>;
18431843
update: (name: string, options?: MemoryStoresUpdateMemoryStoreOptionalParams) => Promise<MemoryStore>;
1844-
updateMemories: (name: string, scope: string, options?: MemoryStoresUpdateMemoriesOptionalParams) => PollerLike<OperationState_2<MemoryStoreUpdateResult>, MemoryStoreUpdateResult>;
1844+
updateMemories: (name: string, scope: string, options?: MemoryStoresUpdateMemoriesOptionalParams) => MemoryStoreUpdatePoller;
18451845
}
18461846

18471847
// @public
@@ -1867,6 +1867,20 @@ export interface MemoryStoresUpdateMemoryStoreOptionalParams extends OperationOp
18671867
metadata?: Record<string, string>;
18681868
}
18691869

1870+
// @public (undocumented)
1871+
export type MemoryStoreUpdateOperationState = OperationState_2<MemoryStoreUpdateResult> & {
1872+
updateId?: string;
1873+
updateStatus?: MemoryStoreUpdateStatus;
1874+
supersededBy?: string;
1875+
};
1876+
1877+
// @public (undocumented)
1878+
export type MemoryStoreUpdatePoller = PollerLike<MemoryStoreUpdateOperationState, MemoryStoreUpdateResult> & {
1879+
readonly updateId?: string;
1880+
readonly updateStatus?: MemoryStoreUpdateStatus;
1881+
readonly supersededBy?: string;
1882+
};
1883+
18701884
// @public
18711885
export interface MemoryStoreUpdateResponse {
18721886
error?: ApiError;

sdk/ai/ai-projects/sample.env

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
AZURE_AI_PROJECT_ENDPOINT="<project connection string from Microsoft Foundry>"
2+
AZURE_AI_MODEL_DEPLOYMENT_NAME="<model deployment name>"
3+
AZURE_AI_CHAT_MODEL_DEPLOYMENT_NAME="<memory chat model deployment name>"
4+
AZURE_AI_EMBEDDING_MODEL_DEPLOYMENT_NAME="<memory embedding model deployment name>"
25
MODEL_DEPLOYMENT_NAME="<model deployment name>"
36
MODEL_API_KEY="<model api key>"
47
MODEL_ENDPOINT="<model endpoint url>"
@@ -22,4 +25,3 @@ IMAGE_GENERATION_MODEL_DEPLOYMENT_NAME="<image generation model deployment name>
2225

2326
MCP_PROJECT_CONNECTION_ID="<mcp project connection id>"
2427
TRIPADVISOR_PROJECT_CONNECTION_ID="<tripadvisor project connection id>"
25-
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
/**
5+
* This sample demonstrates how to add conversational memory to an agent by using the
6+
* Memory Search tool. The agent stores memories in a memory store and can recall them
7+
* in later conversations.
8+
*
9+
* @summary Create an agent with Memory Search, capture memories from a conversation,
10+
* and retrieve them in a new conversation.
11+
*
12+
* @azsdk-weight 100
13+
*/
14+
15+
import { DefaultAzureCredential } from "@azure/identity";
16+
import {
17+
AIProjectClient,
18+
MemoryStoreDefaultDefinition,
19+
MemoryStoreDefaultOptions,
20+
MemorySearchTool,
21+
} from "@azure/ai-projects";
22+
import "dotenv/config";
23+
24+
const projectEndpoint = process.env["AZURE_AI_PROJECT_ENDPOINT"] || "<project endpoint>";
25+
const agentModelDeployment =
26+
process.env["AZURE_AI_MODEL_DEPLOYMENT_NAME"] || "<agent model deployment name>";
27+
const chatModelDeployment =
28+
process.env["AZURE_AI_CHAT_MODEL_DEPLOYMENT_NAME"] || "<memory chat model deployment name>";
29+
const embeddingModelDeployment =
30+
process.env["AZURE_AI_EMBEDDING_MODEL_DEPLOYMENT_NAME"] ||
31+
"<memory embedding model deployment name>";
32+
33+
const memoryStoreName = "my_memory_store_123";
34+
const scope = "user_123";
35+
36+
function delay(ms: number): Promise<void> {
37+
return new Promise((resolve) => setTimeout(resolve, ms));
38+
}
39+
40+
export async function main(): Promise<void> {
41+
const project = new AIProjectClient(projectEndpoint, new DefaultAzureCredential());
42+
const openAIClient = await project.getOpenAIClient();
43+
44+
let conversationId: string | undefined;
45+
let followUpConversationId: string | undefined;
46+
let agentVersion:
47+
| {
48+
name: string;
49+
version: string;
50+
}
51+
| undefined;
52+
53+
try {
54+
// Clean up an existing memory store if it already exists
55+
try {
56+
await project.memoryStores.delete(memoryStoreName);
57+
console.log(`Memory store '${memoryStoreName}' deleted`);
58+
} catch (error: any) {
59+
if (error?.statusCode !== 404) {
60+
throw error;
61+
}
62+
}
63+
64+
// Create a memory store with chat and embedding models
65+
const memoryStore = await project.memoryStores.create(
66+
memoryStoreName,
67+
{
68+
kind: "default",
69+
chat_model: chatModelDeployment,
70+
embedding_model: embeddingModelDeployment,
71+
options: {
72+
user_profile_enabled: true,
73+
chat_summary_enabled: true,
74+
} satisfies MemoryStoreDefaultOptions,
75+
} satisfies MemoryStoreDefaultDefinition,
76+
{
77+
description: "Memory store for agent conversations",
78+
},
79+
);
80+
console.log(
81+
`Created memory store: ${memoryStore.name} (${memoryStore.id}) using chat model '${memoryStore.definition.kind === "default" ? memoryStore.definition.chat_model : chatModelDeployment}'`,
82+
);
83+
84+
// Configure Memory Search tool to attach to the agent
85+
const memorySearchTool: MemorySearchTool = {
86+
type: "memory_search",
87+
memory_store_name: memoryStore.name,
88+
scope,
89+
update_delay: 5, // wait briefly after conversation inactivity before updating memories
90+
};
91+
92+
// Create an agent that will use the Memory Search tool
93+
const agent = await project.agents.createVersion("MemorySearchAgent", {
94+
kind: "prompt",
95+
model: agentModelDeployment,
96+
instructions:
97+
"You are a helpful assistant that remembers user preferences using the memory search tool.",
98+
tools: [memorySearchTool],
99+
});
100+
agentVersion = {
101+
name: agent.name,
102+
version: agent.version,
103+
};
104+
console.log(`Agent created (id: ${agent.id}, name: ${agent.name}, version: ${agent.version})`);
105+
106+
// Start a conversation and provide details the agent should remember
107+
const conversation = await openAIClient.conversations.create();
108+
conversationId = conversation.id;
109+
console.log(`Conversation started (${conversation.id}). Sending a message to seed memories...`);
110+
111+
const firstResponse = await openAIClient.responses.create(
112+
{
113+
input: "I prefer dark roast coffee and usually drink it in the morning.",
114+
conversation: conversation.id,
115+
},
116+
{
117+
body: { agent: { name: agent.name, type: "agent_reference" } },
118+
},
119+
);
120+
console.log(`Initial response: ${firstResponse.output_text}`);
121+
122+
// Allow time for the memory store to update from this conversation
123+
console.log("Waiting for the memory store to capture the new memory...");
124+
await delay(10000);
125+
126+
// Create a follow-up conversation and ask the agent to recall the stored memory
127+
const followUpConversation = await openAIClient.conversations.create();
128+
followUpConversationId = followUpConversation.id;
129+
console.log(`Follow-up conversation started (${followUpConversation.id}).`);
130+
131+
const followUpResponse = await openAIClient.responses.create(
132+
{
133+
input: "Can you remind me of my usual coffee order?",
134+
conversation: followUpConversation.id,
135+
},
136+
{
137+
body: { agent: { name: agent.name, type: "agent_reference" } },
138+
},
139+
);
140+
console.log(`Follow-up response: ${followUpResponse.output_text}`);
141+
} finally {
142+
console.log("\nCleaning up resources...");
143+
if (conversationId) {
144+
await openAIClient.conversations.delete(conversationId);
145+
console.log(`Conversation ${conversationId} deleted`);
146+
}
147+
if (followUpConversationId) {
148+
await openAIClient.conversations.delete(followUpConversationId);
149+
console.log(`Conversation ${followUpConversationId} deleted`);
150+
}
151+
if (agentVersion) {
152+
await project.agents.deleteVersion(agentVersion.name, agentVersion.version);
153+
console.log("Agent deleted");
154+
}
155+
try {
156+
await project.memoryStores.delete(memoryStoreName);
157+
console.log("Memory store deleted");
158+
} catch (error: any) {
159+
if (error?.statusCode !== 404) {
160+
throw error;
161+
}
162+
}
163+
}
164+
165+
console.log("\nMemory Search agent sample completed!");
166+
}
167+
168+
main().catch((err) => {
169+
console.error("The sample encountered an error:", err);
170+
});

sdk/ai/ai-projects/src/api/memoryStores/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,7 @@ export {
2323
MemoryStoresUpdateMemoryStoreOptionalParams,
2424
MemoryStoresCreateMemoryStoreOptionalParams,
2525
} from "./options.js";
26+
export {
27+
MemoryStoreUpdatePoller,
28+
MemoryStoreUpdateOperationState,
29+
} from "./memoryStoreUpdatePoller.js";

0 commit comments

Comments
 (0)