remdb 0.3.7__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (187) hide show
  1. rem/__init__.py +2 -0
  2. rem/agentic/README.md +650 -0
  3. rem/agentic/__init__.py +39 -0
  4. rem/agentic/agents/README.md +155 -0
  5. rem/agentic/agents/__init__.py +8 -0
  6. rem/agentic/context.py +148 -0
  7. rem/agentic/context_builder.py +329 -0
  8. rem/agentic/mcp/__init__.py +0 -0
  9. rem/agentic/mcp/tool_wrapper.py +107 -0
  10. rem/agentic/otel/__init__.py +5 -0
  11. rem/agentic/otel/setup.py +151 -0
  12. rem/agentic/providers/phoenix.py +674 -0
  13. rem/agentic/providers/pydantic_ai.py +572 -0
  14. rem/agentic/query.py +117 -0
  15. rem/agentic/query_helper.py +89 -0
  16. rem/agentic/schema.py +396 -0
  17. rem/agentic/serialization.py +245 -0
  18. rem/agentic/tools/__init__.py +5 -0
  19. rem/agentic/tools/rem_tools.py +231 -0
  20. rem/api/README.md +420 -0
  21. rem/api/main.py +324 -0
  22. rem/api/mcp_router/prompts.py +182 -0
  23. rem/api/mcp_router/resources.py +536 -0
  24. rem/api/mcp_router/server.py +213 -0
  25. rem/api/mcp_router/tools.py +584 -0
  26. rem/api/routers/auth.py +229 -0
  27. rem/api/routers/chat/__init__.py +5 -0
  28. rem/api/routers/chat/completions.py +281 -0
  29. rem/api/routers/chat/json_utils.py +76 -0
  30. rem/api/routers/chat/models.py +124 -0
  31. rem/api/routers/chat/streaming.py +185 -0
  32. rem/auth/README.md +258 -0
  33. rem/auth/__init__.py +26 -0
  34. rem/auth/middleware.py +100 -0
  35. rem/auth/providers/__init__.py +13 -0
  36. rem/auth/providers/base.py +376 -0
  37. rem/auth/providers/google.py +163 -0
  38. rem/auth/providers/microsoft.py +237 -0
  39. rem/cli/README.md +455 -0
  40. rem/cli/__init__.py +8 -0
  41. rem/cli/commands/README.md +126 -0
  42. rem/cli/commands/__init__.py +3 -0
  43. rem/cli/commands/ask.py +566 -0
  44. rem/cli/commands/configure.py +497 -0
  45. rem/cli/commands/db.py +493 -0
  46. rem/cli/commands/dreaming.py +324 -0
  47. rem/cli/commands/experiments.py +1302 -0
  48. rem/cli/commands/mcp.py +66 -0
  49. rem/cli/commands/process.py +245 -0
  50. rem/cli/commands/schema.py +183 -0
  51. rem/cli/commands/serve.py +106 -0
  52. rem/cli/dreaming.py +363 -0
  53. rem/cli/main.py +96 -0
  54. rem/config.py +237 -0
  55. rem/mcp_server.py +41 -0
  56. rem/models/core/__init__.py +49 -0
  57. rem/models/core/core_model.py +64 -0
  58. rem/models/core/engram.py +333 -0
  59. rem/models/core/experiment.py +628 -0
  60. rem/models/core/inline_edge.py +132 -0
  61. rem/models/core/rem_query.py +243 -0
  62. rem/models/entities/__init__.py +43 -0
  63. rem/models/entities/file.py +57 -0
  64. rem/models/entities/image_resource.py +88 -0
  65. rem/models/entities/message.py +35 -0
  66. rem/models/entities/moment.py +123 -0
  67. rem/models/entities/ontology.py +191 -0
  68. rem/models/entities/ontology_config.py +131 -0
  69. rem/models/entities/resource.py +95 -0
  70. rem/models/entities/schema.py +87 -0
  71. rem/models/entities/user.py +85 -0
  72. rem/py.typed +0 -0
  73. rem/schemas/README.md +507 -0
  74. rem/schemas/__init__.py +6 -0
  75. rem/schemas/agents/README.md +92 -0
  76. rem/schemas/agents/core/moment-builder.yaml +178 -0
  77. rem/schemas/agents/core/rem-query-agent.yaml +226 -0
  78. rem/schemas/agents/core/resource-affinity-assessor.yaml +99 -0
  79. rem/schemas/agents/core/simple-assistant.yaml +19 -0
  80. rem/schemas/agents/core/user-profile-builder.yaml +163 -0
  81. rem/schemas/agents/examples/contract-analyzer.yaml +317 -0
  82. rem/schemas/agents/examples/contract-extractor.yaml +134 -0
  83. rem/schemas/agents/examples/cv-parser.yaml +263 -0
  84. rem/schemas/agents/examples/hello-world.yaml +37 -0
  85. rem/schemas/agents/examples/query.yaml +54 -0
  86. rem/schemas/agents/examples/simple.yaml +21 -0
  87. rem/schemas/agents/examples/test.yaml +29 -0
  88. rem/schemas/agents/rem.yaml +128 -0
  89. rem/schemas/evaluators/hello-world/default.yaml +77 -0
  90. rem/schemas/evaluators/rem/faithfulness.yaml +219 -0
  91. rem/schemas/evaluators/rem/lookup-correctness.yaml +182 -0
  92. rem/schemas/evaluators/rem/retrieval-precision.yaml +199 -0
  93. rem/schemas/evaluators/rem/retrieval-recall.yaml +211 -0
  94. rem/schemas/evaluators/rem/search-correctness.yaml +192 -0
  95. rem/services/__init__.py +16 -0
  96. rem/services/audio/INTEGRATION.md +308 -0
  97. rem/services/audio/README.md +376 -0
  98. rem/services/audio/__init__.py +15 -0
  99. rem/services/audio/chunker.py +354 -0
  100. rem/services/audio/transcriber.py +259 -0
  101. rem/services/content/README.md +1269 -0
  102. rem/services/content/__init__.py +5 -0
  103. rem/services/content/providers.py +801 -0
  104. rem/services/content/service.py +676 -0
  105. rem/services/dreaming/README.md +230 -0
  106. rem/services/dreaming/__init__.py +53 -0
  107. rem/services/dreaming/affinity_service.py +336 -0
  108. rem/services/dreaming/moment_service.py +264 -0
  109. rem/services/dreaming/ontology_service.py +54 -0
  110. rem/services/dreaming/user_model_service.py +297 -0
  111. rem/services/dreaming/utils.py +39 -0
  112. rem/services/embeddings/__init__.py +11 -0
  113. rem/services/embeddings/api.py +120 -0
  114. rem/services/embeddings/worker.py +421 -0
  115. rem/services/fs/README.md +662 -0
  116. rem/services/fs/__init__.py +62 -0
  117. rem/services/fs/examples.py +206 -0
  118. rem/services/fs/examples_paths.py +204 -0
  119. rem/services/fs/git_provider.py +935 -0
  120. rem/services/fs/local_provider.py +760 -0
  121. rem/services/fs/parsing-hooks-examples.md +172 -0
  122. rem/services/fs/paths.py +276 -0
  123. rem/services/fs/provider.py +460 -0
  124. rem/services/fs/s3_provider.py +1042 -0
  125. rem/services/fs/service.py +186 -0
  126. rem/services/git/README.md +1075 -0
  127. rem/services/git/__init__.py +17 -0
  128. rem/services/git/service.py +469 -0
  129. rem/services/phoenix/EXPERIMENT_DESIGN.md +1146 -0
  130. rem/services/phoenix/README.md +453 -0
  131. rem/services/phoenix/__init__.py +46 -0
  132. rem/services/phoenix/client.py +686 -0
  133. rem/services/phoenix/config.py +88 -0
  134. rem/services/phoenix/prompt_labels.py +477 -0
  135. rem/services/postgres/README.md +575 -0
  136. rem/services/postgres/__init__.py +23 -0
  137. rem/services/postgres/migration_service.py +427 -0
  138. rem/services/postgres/pydantic_to_sqlalchemy.py +232 -0
  139. rem/services/postgres/register_type.py +352 -0
  140. rem/services/postgres/repository.py +337 -0
  141. rem/services/postgres/schema_generator.py +379 -0
  142. rem/services/postgres/service.py +802 -0
  143. rem/services/postgres/sql_builder.py +354 -0
  144. rem/services/rem/README.md +304 -0
  145. rem/services/rem/__init__.py +23 -0
  146. rem/services/rem/exceptions.py +71 -0
  147. rem/services/rem/executor.py +293 -0
  148. rem/services/rem/parser.py +145 -0
  149. rem/services/rem/queries.py +196 -0
  150. rem/services/rem/query.py +371 -0
  151. rem/services/rem/service.py +527 -0
  152. rem/services/session/README.md +374 -0
  153. rem/services/session/__init__.py +6 -0
  154. rem/services/session/compression.py +360 -0
  155. rem/services/session/reload.py +77 -0
  156. rem/settings.py +1235 -0
  157. rem/sql/002_install_models.sql +1068 -0
  158. rem/sql/background_indexes.sql +42 -0
  159. rem/sql/install_models.sql +1038 -0
  160. rem/sql/migrations/001_install.sql +503 -0
  161. rem/sql/migrations/002_install_models.sql +1202 -0
  162. rem/utils/AGENTIC_CHUNKING.md +597 -0
  163. rem/utils/README.md +583 -0
  164. rem/utils/__init__.py +43 -0
  165. rem/utils/agentic_chunking.py +622 -0
  166. rem/utils/batch_ops.py +343 -0
  167. rem/utils/chunking.py +108 -0
  168. rem/utils/clip_embeddings.py +276 -0
  169. rem/utils/dict_utils.py +98 -0
  170. rem/utils/embeddings.py +423 -0
  171. rem/utils/examples/embeddings_example.py +305 -0
  172. rem/utils/examples/sql_types_example.py +202 -0
  173. rem/utils/markdown.py +16 -0
  174. rem/utils/model_helpers.py +236 -0
  175. rem/utils/schema_loader.py +336 -0
  176. rem/utils/sql_types.py +348 -0
  177. rem/utils/user_id.py +81 -0
  178. rem/utils/vision.py +330 -0
  179. rem/workers/README.md +506 -0
  180. rem/workers/__init__.py +5 -0
  181. rem/workers/dreaming.py +502 -0
  182. rem/workers/engram_processor.py +312 -0
  183. rem/workers/sqs_file_processor.py +193 -0
  184. remdb-0.3.7.dist-info/METADATA +1473 -0
  185. remdb-0.3.7.dist-info/RECORD +187 -0
  186. remdb-0.3.7.dist-info/WHEEL +4 -0
  187. remdb-0.3.7.dist-info/entry_points.txt +2 -0
rem/workers/README.md ADDED
@@ -0,0 +1,506 @@
1
+ # REM Dreaming Worker
2
+
3
+ Background worker for building the REM knowledge graph through memory indexing and insight extraction.
4
+
5
+ ## Overview
6
+
7
+ The dreaming worker processes user content to construct the REM knowledge graph through four core operations:
8
+
9
+ 1. **Ontology Extraction**: Run custom extractors on files/resources for domain-specific knowledge
10
+ 2. **User Model Updates**: Extract and update user profiles from activity
11
+ 3. **Moment Construction**: Identify temporal narratives from resources
12
+ 4. **Resource Affinity**: Build semantic relationships between resources
13
+
14
+ ```
15
+ ┌─────────────────────────────────────────────────────────────┐
16
+ │ Dreaming Worker │
17
+ ├─────────────────────────────────────────────────────────────┤
18
+ │ │
19
+ │ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │
20
+ │ │ User Model │ │ Moment │ │ Resource │ │
21
+ │ │ Updater │ │ Constructor │ │ Affinity │ │
22
+ │ └───────┬───────┘ └───────┬───────┘ └───────┬───────┘ │
23
+ │ │ │ │ │
24
+ │ └──────────────────┼──────────────────┘ │
25
+ │ │ │
26
+ │ ┌───────▼───────┐ │
27
+ │ │ REM Services │ │
28
+ │ │ - Repository │ │
29
+ │ │ - Query │ │
30
+ │ │ - Embedding │ │
31
+ │ └───────────────┘ │
32
+ └─────────────────────────────────────────────────────────────┘
33
+ ```
34
+
35
+ ## Design Philosophy
36
+
37
+ **Lean Implementation**: Push complex utilities to services
38
+ - Worker focuses on orchestration and coordination
39
+ - Complex operations delegated to REM services
40
+ - Minimal business logic in worker code
41
+
42
+ **REM-First**: Use REM system for all reads and writes
43
+ - Query API for resource retrieval
44
+ - PostgresService/Repository for entity persistence
45
+ - Embedding API for vector operations
46
+ - Chat completions for LLM operations
47
+
48
+ **Modular**: Each operation is independent and composable
49
+ - User model updates can run independently
50
+ - Moment construction doesn't depend on affinity
51
+ - Affinity can use different modes (semantic vs LLM)
52
+
53
+ **Observable**: Rich logging and metrics
54
+ - Structured JSON logs for parsing
55
+ - Metrics for resources processed, moments created, edges added
56
+ - OpenTelemetry traces for distributed tracing
57
+
58
+ **Cloud-Native**: Designed for Kubernetes CronJob execution
59
+ - Stateless workers (no shared state)
60
+ - Spot instance tolerant
61
+ - Resource limits enforced
62
+ - Completion tracking
63
+
64
+ ## Operations
65
+
66
+ ### Ontology Extraction
67
+
68
+ Runs custom extractors on user's files and resources to extract domain-specific structured knowledge.
69
+
70
+ **What is an Ontology?**
71
+
72
+ An ontology is domain-specific knowledge extracted from files using custom agent schemas. Unlike generic chunking and embedding:
73
+ - **Structured**: Extracts specific fields (e.g., candidate skills, contract terms, medical diagnoses)
74
+ - **Validated**: Uses JSON Schema for output structure
75
+ - **Searchable**: Semantic search on extracted fields
76
+ - **Queryable**: Direct queries on structured data
77
+
78
+ **Examples:**
79
+ - **Recruitment**: Extract candidate skills, experience, education from CVs
80
+ - **Legal**: Extract parties, obligations, financial terms from contracts
81
+ - **Medical**: Extract diagnoses, medications, treatments from health records
82
+ - **Financial**: Extract metrics, risks, forecasts from reports
83
+
84
+ **How It Works:**
85
+
86
+ ```
87
+ ┌──────────────────────────────────────────────────────────────────┐
88
+ │ 1. Load User's Files/Resources (lookback window) │
89
+ │ - Query files WHERE user_id=X AND updated > cutoff │
90
+ │ - Filter by processing_status='completed' │
91
+ └──────────────────┬───────────────────────────────────────────────┘
92
+
93
+ ┌──────────────────▼───────────────────────────────────────────────┐
94
+ │ 2. Load Matching Extractor Schemas │
95
+ │ - Find schemas with category='ontology-extractor' │
96
+ │ - Check user's OntologyConfig rules (MIME type, tags, etc.) │
97
+ └──────────────────┬───────────────────────────────────────────────┘
98
+
99
+ ┌──────────────────▼───────────────────────────────────────────────┐
100
+ │ 3. Run Extraction (for each file + schema pair) │
101
+ │ - Load schema from database │
102
+ │ - Create agent: create_pydantic_ai_agent(schema.spec) │
103
+ │ - Run agent: result = await agent.run(file.content) │
104
+ │ - Serialize: serialize_agent_result(result.output) │
105
+ └──────────────────┬───────────────────────────────────────────────┘
106
+
107
+ ┌──────────────────▼───────────────────────────────────────────────┐
108
+ │ 4. Generate Embeddings │
109
+ │ - Extract fields: extract_fields_for_embedding() │
110
+ │ - Generate embedding: generate_embeddings() │
111
+ └──────────────────┬───────────────────────────────────────────────┘
112
+
113
+ ┌──────────────────▼───────────────────────────────────────────────┐
114
+ │ 5. Store Ontology Entity │
115
+ │ - Ontology(extracted_data=..., embedding_text=...) │
116
+ │ - Save via ontology_repo.upsert() │
117
+ └──────────────────────────────────────────────────────────────────┘
118
+ ```
119
+
120
+ **Key Principle: No Separate Service**
121
+
122
+ Ontology extraction is NOT a separate service. It's just:
123
+ - Load schema (existing repository)
124
+ - Run agent (existing `create_pydantic_ai_agent()`)
125
+ - Serialize result (existing `serialize_agent_result()`)
126
+ - Extract embedding text (util: `extract_fields_for_embedding()`)
127
+ - Generate embedding (existing `generate_embeddings()`)
128
+ - Store ontology (existing repository)
129
+
130
+ All logic lives in the dreaming worker. Maximum DRY.
131
+
132
+ **Process:**
133
+ 1. Query user's files/resources (lookback window)
134
+ 2. For each file, find matching extractor schemas
135
+ 3. Run agent extraction on file content
136
+ 4. Extract embedding text from configured fields
137
+ 5. Generate embeddings for semantic search
138
+ 6. Store Ontology entity
139
+
140
+ **Output:**
141
+ - Ontology entities with:
142
+ - `extracted_data`: Arbitrary structured JSON (the gold!)
143
+ - `file_id`: Link to source file
144
+ - `agent_schema_id`: Which agent extracted this
145
+ - `provider_name`, `model_name`: LLM used
146
+ - `confidence_score`: Optional quality metric (0.0-1.0)
147
+ - `embedding_text`: Text for semantic search
148
+
149
+ **CLI:**
150
+ ```bash
151
+ # Run custom extractor on user's data
152
+ rem dreaming custom --user-id user-123 --extractor cv-parser-v1
153
+
154
+ # With lookback and limit
155
+ rem dreaming custom --user-id user-123 --extractor contract-analyzer-v1 \\
156
+ --lookback-hours 168 --limit 50
157
+
158
+ # Override provider
159
+ rem dreaming custom --user-id user-123 --extractor cv-parser-v1 \\
160
+ --provider anthropic --model claude-sonnet-4-5
161
+ ```
162
+
163
+ **Frequency:** On-demand or as part of full workflow
164
+
165
+ **Example Extractors:**
166
+
167
+ **CV Parser** (`cv-parser-v1.yaml`):
168
+ ```yaml
169
+ Extracts: candidate_name, email, skills, experience, education, certifications
170
+ Use case: Recruitment consultants processing resumes
171
+ Embedding fields: candidate_name, professional_summary, skills, experience
172
+ ```
173
+
174
+ **Contract Analyzer** (`contract-analyzer-v1.yaml`):
175
+ ```yaml
176
+ Extracts: parties, financial_terms, key_obligations, risk_flags
177
+ Use case: Legal teams analyzing supplier/partnership agreements
178
+ Embedding fields: contract_title, contract_type, parties, key_obligations
179
+ ```
180
+
181
+ **Creating Custom Extractors:**
182
+
183
+ 1. Define JSON Schema with output structure
184
+ 2. Add system prompt in `description` field
185
+ 3. Specify `embedding_fields` in `json_schema_extra`
186
+ 4. Optionally specify `provider_configs` for multi-provider testing
187
+ 5. Save to database as Schema entity
188
+ 6. Create OntologyConfig rules (MIME type, URI pattern, tags)
189
+
190
+ See `rem/schemas/ontology_extractors/` for examples.
191
+
192
+ ### User Model Updates
193
+
194
+ Reads recent activity to generate comprehensive user profiles.
195
+
196
+ **Process:**
197
+ 1. Query REM for recent sessions, moments, resources
198
+ 2. Generate user summary using LLM
199
+ 3. Update User entity with summary and metadata
200
+ 4. Add graph edges to key resources and moments
201
+
202
+ **Output:**
203
+ - Updated User entity with summary field
204
+ - Graph edges to recent resources (rel_type="engaged_with")
205
+ - Activity level classification (active, moderate, inactive)
206
+ - Interest and topic extraction
207
+
208
+ **CLI:**
209
+ ```bash
210
+ rem-dreaming user-model --tenant-id=tenant-123
211
+ ```
212
+
213
+ **Frequency:** Daily (runs as part of full workflow)
214
+
215
+ ### Moment Construction
216
+
217
+ Extracts temporal narratives from resources.
218
+
219
+ **Process:**
220
+ 1. Query REM for recent resources (lookback window)
221
+ 2. Use LLM to extract temporal narratives
222
+ 3. Create Moment entities with temporal boundaries
223
+ 4. Link moments to source resources via graph edges
224
+ 5. Generate embeddings for moment content
225
+
226
+ **Output:**
227
+ - Moment entities with:
228
+ - Temporal boundaries (starts_timestamp, ends_timestamp)
229
+ - Present persons
230
+ - Emotion tags (focused, excited, concerned)
231
+ - Topic tags (sprint-planning, api-design)
232
+ - Natural language summaries
233
+ - Graph edges to source resources (rel_type="extracted_from")
234
+
235
+ **CLI:**
236
+ ```bash
237
+ # Process last 24 hours
238
+ rem-dreaming moments --tenant-id=tenant-123
239
+
240
+ # Custom lookback
241
+ rem-dreaming moments --tenant-id=tenant-123 --lookback-hours=48
242
+
243
+ # Limit resources processed
244
+ rem-dreaming moments --tenant-id=tenant-123 --limit=100
245
+ ```
246
+
247
+ **Frequency:** Daily or on-demand
248
+
249
+ ### Resource Affinity
250
+
251
+ Builds semantic relationships between resources.
252
+
253
+ **Modes:**
254
+
255
+ **Semantic Mode (Fast)**
256
+ - Vector similarity search
257
+ - Creates edges for similar resources (threshold: 0.7)
258
+ - No LLM calls, pure vector math
259
+ - Cheap and fast
260
+ - Good for frequent updates (every 6 hours)
261
+
262
+ **LLM Mode (Intelligent)**
263
+ - LLM assessment of relationship context
264
+ - Rich metadata in edge properties
265
+ - Expensive (many LLM calls)
266
+ - ALWAYS use --limit to control costs
267
+ - Good for deep weekly analysis
268
+
269
+ **Process:**
270
+ 1. Query REM for recent resources
271
+ 2. For each resource:
272
+ - Semantic: Query similar resources by vector
273
+ - LLM: Assess relationships using LLM
274
+ 3. Create graph edges via REM repository
275
+ 4. Update resource entities with affinity edges
276
+
277
+ **Output:**
278
+ - Graph edges between resources with:
279
+ - rel_type: semantic_similar, references, builds_on, etc.
280
+ - weight: Relationship strength (0.0-1.0)
281
+ - properties: Rich metadata (confidence, context)
282
+
283
+ **CLI:**
284
+ ```bash
285
+ # Semantic mode (fast, cheap)
286
+ rem-dreaming affinity --tenant-id=tenant-123
287
+
288
+ # LLM mode (intelligent, expensive)
289
+ rem-dreaming affinity --tenant-id=tenant-123 --use-llm --limit=100
290
+
291
+ # Custom lookback
292
+ rem-dreaming affinity --tenant-id=tenant-123 --lookback-hours=168
293
+ ```
294
+
295
+ **Frequency:**
296
+ - Semantic: Every 6 hours
297
+ - LLM: Weekly (Sundays)
298
+
299
+ ### Full Workflow
300
+
301
+ Runs all operations in sequence.
302
+
303
+ **Process:**
304
+ 1. Update user model
305
+ 2. Construct moments
306
+ 3. Build resource affinity
307
+
308
+ **CLI:**
309
+ ```bash
310
+ # Single tenant
311
+ rem-dreaming full --tenant-id=tenant-123
312
+
313
+ # All active tenants (daily cron)
314
+ rem-dreaming full --all-tenants
315
+
316
+ # Use LLM affinity mode
317
+ rem-dreaming full --tenant-id=tenant-123 --use-llm-affinity
318
+ ```
319
+
320
+ **Frequency:** Daily at 3 AM UTC
321
+
322
+ ## Environment Variables
323
+
324
+ ```bash
325
+ # REM Configuration
326
+ REM_API_URL=http://rem-api:8000 # REM API endpoint
327
+ REM_EMBEDDING_PROVIDER=text-embedding-3-small # Embedding provider
328
+ REM_DEFAULT_MODEL=gpt-4o # LLM model
329
+ REM_LOOKBACK_HOURS=24 # Default lookback window
330
+
331
+ # API Keys
332
+ OPENAI_API_KEY=sk-... # OpenAI API key
333
+ ANTHROPIC_API_KEY=sk-ant-... # Anthropic API key (optional)
334
+ ```
335
+
336
+ ## Kubernetes Deployment
337
+
338
+ ### CronJobs
339
+
340
+ **Daily Full Workflow** (3 AM UTC)
341
+ ```yaml
342
+ schedule: "0 3 * * *"
343
+ command: rem-dreaming full --all-tenants
344
+ resources: 256Mi memory, 250m CPU
345
+ ```
346
+
347
+ **Frequent Affinity Updates** (Every 6 hours)
348
+ ```yaml
349
+ schedule: "0 */6 * * *"
350
+ command: rem-dreaming affinity --all-tenants --lookback-hours=6
351
+ resources: 256Mi memory, 250m CPU
352
+ ```
353
+
354
+ **Weekly LLM Affinity** (Sundays 2 AM)
355
+ ```yaml
356
+ schedule: "0 2 * * 0"
357
+ command: rem-dreaming affinity --all-tenants --use-llm --limit=500
358
+ resources: 512Mi memory, 500m CPU
359
+ ```
360
+
361
+ ### Deployment
362
+
363
+ ```bash
364
+ # Apply via Kustomize
365
+ kubectl apply -k manifests/application/rem-stack/base
366
+
367
+ # Or via ArgoCD
368
+ kubectl apply -f manifests/application/rem-stack/argocd-staging.yaml
369
+ ```
370
+
371
+ ### Monitoring
372
+
373
+ ```bash
374
+ # List CronJobs
375
+ kubectl get cronjobs -n rem-app
376
+
377
+ # List Jobs
378
+ kubectl get jobs -n rem-app
379
+
380
+ # Follow logs
381
+ kubectl logs -f -l app=rem-dreaming -n rem-app
382
+
383
+ # Manual trigger
384
+ kubectl create job dreaming-manual-$(date +%s) \
385
+ --from=cronjob/rem-dreaming-worker \
386
+ -n rem-app
387
+ ```
388
+
389
+ ## Cost Management
390
+
391
+ ### Semantic Mode (Cheap)
392
+ - Only embedding costs (if generating new embeddings)
393
+ - Vector similarity is computational, not API calls
394
+ - Good for frequent updates
395
+
396
+ ### LLM Mode (Expensive)
397
+ - Each resource pair = 1 LLM API call
398
+ - 100 resources = potentially 5,000 API calls
399
+ - ALWAYS use --limit to control costs
400
+ - Monitor costs in LLM provider dashboard
401
+
402
+ ### Best Practices
403
+ 1. Use semantic mode for frequent updates (6 hours)
404
+ 2. Use LLM mode sparingly (weekly)
405
+ 3. Always use --limit with LLM mode
406
+ 4. Start with small lookback windows (24-48 hours)
407
+ 5. Monitor embedding/LLM costs regularly
408
+
409
+ ## Error Handling
410
+
411
+ **Graceful Degradation**
412
+ - Continue on partial failures
413
+ - Don't fail entire job if one tenant fails
414
+ - Log errors with context for debugging
415
+
416
+ **Retry Logic**
417
+ - Exponential backoff for transient errors
418
+ - Retry up to 3 times for API failures
419
+ - Don't retry on validation errors
420
+
421
+ **Job Status**
422
+ - Save success/failure status to database
423
+ - Include error messages and stack traces
424
+ - Enable post-mortem debugging
425
+
426
+ ## Performance
427
+
428
+ **Batch Operations**
429
+ - Minimize round trips to REM API
430
+ - Batch entity creation (upsert multiple)
431
+ - Batch embedding generation
432
+
433
+ **Streaming**
434
+ - Process large result sets incrementally
435
+ - Don't load all resources into memory
436
+ - Use cursor-based pagination
437
+
438
+ **Parallelization**
439
+ - Use asyncio for concurrent operations
440
+ - Process multiple tenants in parallel
441
+ - Limit concurrency to avoid overwhelming API
442
+
443
+ **Caching**
444
+ - Cache embeddings (REM handles this)
445
+ - Cache LLM responses when possible
446
+ - Use etags for conditional requests
447
+
448
+ ## Development
449
+
450
+ ### Local Testing
451
+
452
+ ```bash
453
+ # Set environment variables
454
+ export REM_API_URL=http://localhost:8000
455
+ export OPENAI_API_KEY=sk-...
456
+
457
+ # Run user model update
458
+ python -m rem.cli.dreaming user-model --tenant-id=tenant-test
459
+
460
+ # Run moment construction
461
+ python -m rem.cli.dreaming moments --tenant-id=tenant-test --lookback-hours=24
462
+
463
+ # Run affinity (semantic mode)
464
+ python -m rem.cli.dreaming affinity --tenant-id=tenant-test
465
+
466
+ # Run full workflow
467
+ python -m rem.cli.dreaming full --tenant-id=tenant-test
468
+ ```
469
+
470
+ ### Testing with Docker
471
+
472
+ ```bash
473
+ # Build image
474
+ docker build -t rem-stack:latest -f Dockerfile .
475
+
476
+ # Run worker
477
+ docker run --rm \
478
+ -e REM_API_URL=http://host.docker.internal:8000 \
479
+ -e OPENAI_API_KEY=$OPENAI_API_KEY \
480
+ rem-stack:latest \
481
+ python -m rem.cli.dreaming full --tenant-id=tenant-test
482
+ ```
483
+
484
+ ## Architecture Decisions
485
+
486
+ ### Why Lean?
487
+ Complex operations belong in services (postgres, embeddings, etc.), not workers. Workers orchestrate, services execute.
488
+
489
+ ### Why REM-First?
490
+ Using REM APIs ensures consistency, observability, and reusability. No direct database access in workers.
491
+
492
+ ### Why Separate Modes?
493
+ Semantic mode is cheap and fast (frequent updates). LLM mode is expensive and intelligent (deep analysis).
494
+
495
+ ### Why CronJob?
496
+ Batch processing is more efficient than continuous streaming. Daily indexing provides fresh insights without constant load.
497
+
498
+ ### Why Spot Instances?
499
+ Workers are fault-tolerant and can restart. Spot instances reduce costs by 70% with minimal impact.
500
+
501
+ ## Related Documentation
502
+
503
+ - [Engram Specification](../../models/core/engram.py) - Core memory model
504
+ - [REM Query API](../../api/) - Query interface
505
+ - [PostgresService & Repository](../../services/postgres/) - Entity persistence
506
+ - [CLAUDE.md](../../../../CLAUDE.md) - Overall architecture
@@ -0,0 +1,5 @@
1
+ """Background workers for processing tasks."""
2
+
3
+ from .sqs_file_processor import SQSFileProcessor
4
+
5
+ __all__ = ["SQSFileProcessor"]