Skip to content

Commit df4ff5e

Browse files
aayush3011Aayush Kataria
andauthored
Updating cosmos db topology to use 3 containers (#16)
* Updating cosmos db topology to use 3 containers * resolving comments * resolving comments * resolving comments * resolving comments * resolving comments * resolving comments --------- Co-authored-by: Aayush Kataria <aayushkataria@Aayushs-MacBook-Pro-2.local>
1 parent e0de0b1 commit df4ff5e

88 files changed

Lines changed: 4420 additions & 2238 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.env.template

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,12 @@ COSMOS_DB__accountEndpoint=https://<your-account>.documents.azure.com:443/
1010
# letting you create databases/containers without RBAC role assignments.
1111
# Leave blank to use DefaultAzureCredential / managed identity.
1212
COSMOS_DB_KEY=
13+
# Database name. Must match what the Function App reads (COSMOS_DB_DATABASE there).
14+
# Default is "ai_memory"; change only if your infra deploys a different name.
1315
COSMOS_DB_DATABASE=ai_memory
14-
COSMOS_DB_CONTAINER=memories
16+
COSMOS_DB_MEMORIES_CONTAINER="memories"
17+
COSMOS_DB_SUMMARIES_CONTAINER="memories_summaries"
18+
COSMOS_DB_TURNS_CONTAINER="memories_turns"
1519
COSMOS_DB_COUNTERS_CONTAINER=counter
1620
COSMOS_DB_LEASE_CONTAINER=leases
1721
# Throughput mode for all required Cosmos DB containers created by the toolkit
@@ -29,6 +33,21 @@ THREAD_SUMMARY_EVERY_N=10
2933
FACT_EXTRACTION_EVERY_N=1
3034
USER_SUMMARY_EVERY_N=20
3135

36+
# ---- Processor ownership (in-process SDK vs. Function App / Durable) ----
37+
# Controls which side runs the auto-trigger to avoid double-firing when both
38+
# the SDK and the Function App are deployed against the same database.
39+
#
40+
# * Unset / blank -> SDK auto-trigger fires; FA change-feed SKIPS.
41+
# (Pure SDK deployments — no env config needed.)
42+
# * "inprocess" -> SDK auto-trigger fires; FA change-feed SKIPS.
43+
# * "durable" -> SDK auto-trigger SKIPS; FA change-feed fires.
44+
#
45+
# The contract is asymmetric by design: the FA defaults to skip (default-deny)
46+
# so a fresh FA deploy next to an existing SDK install does not race. If you
47+
# run the Function App, you MUST set this to "durable" or processing will
48+
# silently no-op.
49+
MEMORY_PROCESSOR_OWNER=
50+
3251
# ---- AI Foundry / Azure OpenAI ----
3352
AI_FOUNDRY_ENDPOINT=https://<your-account>.openai.azure.com/
3453
AI_FOUNDRY_API_KEY=
@@ -39,3 +58,6 @@ AI_FOUNDRY_EMBEDDING_DISTANCE_FUNCTION=cosine
3958
COSMOS_DB_FULL_TEXT_LANGUAGE=en-US
4059

4160
AI_FOUNDRY_CHAT_DEPLOYMENT_NAME=<your-model-deployment>
61+
# Optional. Pin the Azure OpenAI REST API version used by chat and embeddings
62+
# clients. Leave blank to use the toolkit default ("2024-12-01-preview").
63+
AZURE_OPENAI_API_VERSION=

Docs/azure_testing.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ az functionapp config appsettings set \
105105
--settings \
106106
COSMOS_DB_ENDPOINT="https://<cosmos-account-name>.documents.azure.com:443/" \
107107
COSMOS_DB_DATABASE="ai_memory" \
108-
COSMOS_DB_CONTAINER="memories" \
108+
COSMOS_DB_MEMORIES_CONTAINER="memories" \
109109
COSMOS_DB_COUNTERS_CONTAINER="counter" \
110110
COSMOS_DB_LEASE_CONTAINER="leases" \
111111
COSMOS_DB_THROUGHPUT_MODE="serverless" \
@@ -120,7 +120,7 @@ az functionapp config appsettings set \
120120
MEMORY_PROCESSOR_OWNER="durable"
121121
```
122122

123-
`COSMOS_DB_THROUGHPUT_MODE=serverless` is the default and creates the `memories`, `counter`, and `leases` containers without specifying RU/s. Set `COSMOS_DB_THROUGHPUT_MODE=autoscale` to apply the shared `COSMOS_DB_AUTOSCALE_MAX_RU` cap to all required containers.
123+
`COSMOS_DB_THROUGHPUT_MODE=serverless` is the default and creates the `memories`, `memories_turns`, `memories_summaries`, `counter`, and `leases` containers without specifying RU/s. Set `COSMOS_DB_THROUGHPUT_MODE=autoscale` to apply the shared `COSMOS_DB_AUTOSCALE_MAX_RU` cap to all required containers.
124124

125125
`MEMORY_PROCESSOR_OWNER=durable` tells the SDK that the deployed Function App owns processing, so any `CosmosMemoryClient` pointed at the same container will skip its in-process auto-trigger and avoid double-extraction. See the README's processor-ownership table for details.
126126

@@ -178,7 +178,7 @@ Update `.env` to point at Azure instead of localhost:
178178
```env
179179
COSMOS_DB_ENDPOINT=https://<cosmos-account-name>.documents.azure.com:443/
180180
COSMOS_DB_DATABASE=ai_memory
181-
COSMOS_DB_CONTAINER=memories
181+
COSMOS_DB_MEMORIES_CONTAINER=memories
182182
COSMOS_DB_COUNTERS_CONTAINER=counter
183183
COSMOS_DB_LEASE_CONTAINER=leases
184184
COSMOS_DB_THROUGHPUT_MODE=serverless
@@ -213,7 +213,7 @@ load_dotenv()
213213
memory = CosmosMemoryClient(
214214
cosmos_endpoint=os.getenv("COSMOS_DB_ENDPOINT"),
215215
cosmos_database=os.getenv("COSMOS_DB_DATABASE", "ai_memory"),
216-
cosmos_container=os.getenv("COSMOS_DB_CONTAINER", "memories"),
216+
cosmos_container=os.getenv("COSMOS_DB_MEMORIES_CONTAINER", "memories"),
217217
cosmos_counter_container=os.getenv("COSMOS_DB_COUNTERS_CONTAINER", "counter"),
218218
cosmos_lease_container=os.getenv("COSMOS_DB_LEASE_CONTAINER", "leases"),
219219
cosmos_throughput_mode=os.getenv("COSMOS_DB_THROUGHPUT_MODE", "serverless"),
@@ -242,7 +242,7 @@ load_dotenv()
242242
memory = AsyncCosmosMemoryClient(
243243
cosmos_endpoint=os.getenv("COSMOS_DB_ENDPOINT"),
244244
cosmos_database=os.getenv("COSMOS_DB_DATABASE", "ai_memory"),
245-
cosmos_container=os.getenv("COSMOS_DB_CONTAINER", "memories"),
245+
cosmos_container=os.getenv("COSMOS_DB_MEMORIES_CONTAINER", "memories"),
246246
cosmos_counter_container=os.getenv("COSMOS_DB_COUNTERS_CONTAINER", "counter"),
247247
cosmos_lease_container=os.getenv("COSMOS_DB_LEASE_CONTAINER", "leases"),
248248
cosmos_throughput_mode=os.getenv("COSMOS_DB_THROUGHPUT_MODE", "serverless"),
@@ -258,7 +258,7 @@ await memory.connect_cosmos()
258258
await memory.create_memory_store()
259259
```
260260

261-
This provisions the `memories`, `counter`, and `leases` containers. `serverless` is the default throughput mode; if you set `COSMOS_DB_THROUGHPUT_MODE=autoscale`, the shared `COSMOS_DB_AUTOSCALE_MAX_RU` value is applied to all three containers.
261+
This provisions the `memories`, `memories_turns`, `memories_summaries`, `counter`, and `leases` containers. `serverless` is the default throughput mode; if you set `COSMOS_DB_THROUGHPUT_MODE=autoscale`, the shared `COSMOS_DB_AUTOSCALE_MAX_RU` value is applied to all five containers.
262262

263263
---
264264

@@ -314,9 +314,9 @@ for i in range(10):
314314

315315
# Wait for the change-feed processor to catch up, then read derived memories.
316316
import time; time.sleep(15)
317-
print(memory.get_memories(user_id="user-1", thread_id="thread-1", memory_types=["summary"]))
317+
print(memory.get_thread_summary(user_id="user-1", thread_id="thread-1"))
318318
print(memory.get_memories(user_id="user-1", memory_types=["fact"]))
319-
print(memory.get_memories(user_id="user-1", memory_types=["user_summary"]))
319+
print(memory.get_user_summary(user_id="user-1"))
320320
```
321321

322322
### Change feed auto-processing
@@ -339,7 +339,7 @@ for i in range(3):
339339
# Wait a few seconds for the change feed to trigger, then check:
340340
import time
341341
time.sleep(10)
342-
results = memory.get_memories(user_id="user-1", thread_id=thread_id, memory_types=["summary"])
342+
results = memory.get_thread_summary(user_id="user-1", thread_id=thread_id)
343343
print(results) # Should contain an auto-generated summary
344344
```
345345

@@ -348,9 +348,9 @@ Check the Function App logs to confirm the `on_memory_change` trigger fired and
348348
### Verify stored results
349349

350350
```python
351-
print(memory.get_memories(user_id="user-1", memory_types=["summary"]))
351+
print(memory.get_thread_summary(user_id="user-1", thread_id="thread-1"))
352352
print(memory.get_memories(user_id="user-1", memory_types=["fact"]))
353-
print(memory.get_memories(user_id="user-1", memory_types=["user_summary"]))
353+
print(memory.get_user_summary(user_id="user-1"))
354354
```
355355

356356
---

Docs/concepts.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,16 +179,18 @@ Set any value to `0` to disable that processing type. For example, setting `THRE
179179

180180
| Container | Partition Key | Purpose |
181181
|-----------|---------------|---------|
182-
| `memories` | `/user_id`, `/thread_id` (hierarchical) | Existing memory store |
182+
| `memories` | `/user_id`, `/thread_id` (hierarchical) | Durable derived memories (`fact`, `episodic`, `procedural`) |
183+
| `memories_turns` | `/user_id`, `/thread_id` (hierarchical) | Raw conversation turns (`turn`) — append-only, TTL-pruned |
184+
| `memories_summaries` | `/user_id`, `/thread_id` (hierarchical) | Thread + user summaries (`thread_summary`, `user_summary`) |
183185
| `counter` | `/user_id`, `/thread_id` (hierarchical) | Message count tracking for automatic processing |
184186
| `leases` | `/id` | Change feed checkpointing container created by `create_memory_store()` |
185187

186188
### Throughput configuration
187189

188190
The toolkit provisions all required Cosmos containers under one shared throughput mode:
189191

190-
- `serverless` is the default. The toolkit creates the `memories`, `counter`, and `leases` containers without specifying RU/s.
191-
- `autoscale` applies the shared `COSMOS_DB_AUTOSCALE_MAX_RU` cap to all three containers.
192+
- `serverless` is the default. The toolkit creates the `memories`, `memories_turns`, `memories_summaries`, `counter`, and `leases` containers without specifying RU/s.
193+
- `autoscale` applies the shared `COSMOS_DB_AUTOSCALE_MAX_RU` cap to all five containers.
192194

193195
This keeps the change feed dependencies aligned with the main memory store instead of letting the Functions trigger create the lease container independently.
194196

Docs/local_testing.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ Minimum `.env` values:
7171
```env
7272
COSMOS_DB_ENDPOINT=https://<your-account>.documents.azure.com:443/
7373
COSMOS_DB_DATABASE=ai_memory
74-
COSMOS_DB_CONTAINER=memories
74+
COSMOS_DB_MEMORIES_CONTAINER=memories
7575
COSMOS_DB_COUNTERS_CONTAINER=counter
7676
COSMOS_DB_LEASE_CONTAINER=leases
7777
COSMOS_DB_THROUGHPUT_MODE=serverless
@@ -115,9 +115,9 @@ No Azure resources are required for local in-memory operations.
115115

116116
```python
117117
import uuid
118-
from agent_memory_toolkit import AgentMemory
118+
from agent_memory_toolkit import CosmosMemoryClient
119119

120-
memory = AgentMemory(use_default_credential=False)
120+
memory = CosmosMemoryClient(use_default_credential=False)
121121

122122
THREAD_ID = str(uuid.uuid4())
123123

@@ -133,7 +133,7 @@ memory.delete_local(mem_id)
133133
print(f"Remaining: {len(memory.get_local())}")
134134
```
135135

136-
`AsyncAgentMemory` works the same way for local operations (local methods are synchronous).
136+
`AsyncCosmosMemoryClient` works the same way for local operations (local methods are synchronous).
137137

138138
---
139139

@@ -153,14 +153,14 @@ Then run a minimal smoke test:
153153
import os, uuid
154154
from dotenv import load_dotenv
155155
from azure.identity import DefaultAzureCredential
156-
from agent_memory_toolkit import AgentMemory
156+
from agent_memory_toolkit import CosmosMemoryClient
157157

158158
load_dotenv()
159159

160-
memory = AgentMemory(
160+
memory = CosmosMemoryClient(
161161
cosmos_endpoint=os.getenv("COSMOS_DB_ENDPOINT"),
162162
cosmos_database=os.getenv("COSMOS_DB_DATABASE"),
163-
cosmos_container=os.getenv("COSMOS_DB_CONTAINER"),
163+
cosmos_container=os.getenv("COSMOS_DB_MEMORIES_CONTAINER"),
164164
cosmos_counter_container=os.getenv("COSMOS_DB_COUNTERS_CONTAINER", "counter"),
165165
cosmos_lease_container=os.getenv("COSMOS_DB_LEASE_CONTAINER", "leases"),
166166
cosmos_throughput_mode=os.getenv("COSMOS_DB_THROUGHPUT_MODE", "serverless"),
@@ -196,14 +196,14 @@ for r in results:
196196
import os, uuid
197197
from dotenv import load_dotenv
198198
from azure.identity.aio import DefaultAzureCredential as AsyncDefaultAzureCredential
199-
from agent_memory_toolkit.aio import AsyncAgentMemory
199+
from agent_memory_toolkit.aio import AsyncCosmosMemoryClient
200200

201201
load_dotenv()
202202

203-
memory = AsyncAgentMemory(
203+
memory = AsyncCosmosMemoryClient(
204204
cosmos_endpoint=os.getenv("COSMOS_DB_ENDPOINT"),
205205
cosmos_database=os.getenv("COSMOS_DB_DATABASE"),
206-
cosmos_container=os.getenv("COSMOS_DB_CONTAINER"),
206+
cosmos_container=os.getenv("COSMOS_DB_MEMORIES_CONTAINER"),
207207
cosmos_counter_container=os.getenv("COSMOS_DB_COUNTERS_CONTAINER", "counter"),
208208
cosmos_lease_container=os.getenv("COSMOS_DB_LEASE_CONTAINER", "leases"),
209209
cosmos_throughput_mode=os.getenv("COSMOS_DB_THROUGHPUT_MODE", "serverless"),
@@ -219,7 +219,7 @@ memory = AsyncAgentMemory(
219219
await memory.connect_cosmos(
220220
endpoint=os.getenv("COSMOS_DB_ENDPOINT"),
221221
database=os.getenv("COSMOS_DB_DATABASE"),
222-
container=os.getenv("COSMOS_DB_CONTAINER"),
222+
container=os.getenv("COSMOS_DB_MEMORIES_CONTAINER"),
223223
credential=AsyncDefaultAzureCredential(),
224224
)
225225
await memory.create_memory_store()

0 commit comments

Comments
 (0)