alma-memory 0.5.0__tar.gz → 0.5.1__tar.gz
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.
- {alma_memory-0.5.0 → alma_memory-0.5.1}/PKG-INFO +42 -8
- {alma_memory-0.5.0 → alma_memory-0.5.1}/README.md +36 -6
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/__init__.py +33 -1
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/core.py +124 -16
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/extraction/auto_learner.py +4 -3
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/graph/__init__.py +26 -1
- alma_memory-0.5.1/alma/graph/backends/__init__.py +32 -0
- alma_memory-0.5.1/alma/graph/backends/kuzu.py +624 -0
- alma_memory-0.5.1/alma/graph/backends/memgraph.py +432 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/integration/claude_agents.py +22 -10
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/learning/protocols.py +3 -3
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/mcp/tools.py +9 -11
- alma_memory-0.5.1/alma/observability/__init__.py +84 -0
- alma_memory-0.5.1/alma/observability/config.py +302 -0
- alma_memory-0.5.1/alma/observability/logging.py +424 -0
- alma_memory-0.5.1/alma/observability/metrics.py +583 -0
- alma_memory-0.5.1/alma/observability/tracing.py +440 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/retrieval/engine.py +65 -4
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/storage/__init__.py +29 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/storage/azure_cosmos.py +343 -132
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/storage/base.py +58 -0
- alma_memory-0.5.1/alma/storage/constants.py +103 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/storage/file_based.py +3 -8
- alma_memory-0.5.1/alma/storage/migrations/__init__.py +21 -0
- alma_memory-0.5.1/alma/storage/migrations/base.py +321 -0
- alma_memory-0.5.1/alma/storage/migrations/runner.py +323 -0
- alma_memory-0.5.1/alma/storage/migrations/version_stores.py +337 -0
- alma_memory-0.5.1/alma/storage/migrations/versions/__init__.py +11 -0
- alma_memory-0.5.1/alma/storage/migrations/versions/v1_0_0.py +373 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/storage/postgresql.py +185 -78
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/storage/sqlite_local.py +149 -50
- alma_memory-0.5.1/alma/testing/__init__.py +46 -0
- alma_memory-0.5.1/alma/testing/factories.py +301 -0
- alma_memory-0.5.1/alma/testing/mocks.py +389 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma_memory.egg-info/PKG-INFO +42 -8
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma_memory.egg-info/SOURCES.txt +17 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma_memory.egg-info/requires.txt +6 -1
- {alma_memory-0.5.0 → alma_memory-0.5.1}/pyproject.toml +9 -2
- alma_memory-0.5.0/alma/graph/backends/__init__.py +0 -18
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/confidence/__init__.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/confidence/engine.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/confidence/types.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/config/__init__.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/config/loader.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/consolidation/__init__.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/consolidation/engine.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/consolidation/prompts.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/domains/__init__.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/domains/factory.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/domains/schemas.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/domains/types.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/events/__init__.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/events/emitter.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/events/storage_mixin.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/events/types.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/events/webhook.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/exceptions.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/extraction/__init__.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/extraction/extractor.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/graph/backends/memory.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/graph/backends/neo4j.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/graph/base.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/graph/extraction.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/graph/store.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/harness/__init__.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/harness/base.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/harness/domains.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/initializer/__init__.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/initializer/initializer.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/initializer/types.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/integration/__init__.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/integration/helena.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/integration/victor.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/learning/__init__.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/learning/forgetting.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/learning/heuristic_extractor.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/learning/validation.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/mcp/__init__.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/mcp/__main__.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/mcp/resources.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/mcp/server.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/progress/__init__.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/progress/tracker.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/progress/types.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/py.typed +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/retrieval/__init__.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/retrieval/cache.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/retrieval/embeddings.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/retrieval/scoring.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/session/__init__.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/session/manager.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/session/types.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/storage/chroma.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/storage/pinecone.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/storage/qdrant.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma/types.py +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma_memory.egg-info/dependency_links.txt +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/alma_memory.egg-info/top_level.txt +0 -0
- {alma_memory-0.5.0 → alma_memory-0.5.1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: alma-memory
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.1
|
|
4
4
|
Summary: Agent Learning Memory Architecture - Persistent memory for AI agents
|
|
5
5
|
Author-email: RBKunnela <aiagentsprompt@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -41,6 +41,10 @@ Requires-Dist: pinecone>=3.0.0; extra == "pinecone"
|
|
|
41
41
|
Provides-Extra: mcp
|
|
42
42
|
Requires-Dist: pydantic>=2.0.0; extra == "mcp"
|
|
43
43
|
Requires-Dist: aiohttp>=3.9.0; extra == "mcp"
|
|
44
|
+
Provides-Extra: observability
|
|
45
|
+
Requires-Dist: opentelemetry-api>=1.20.0; extra == "observability"
|
|
46
|
+
Requires-Dist: opentelemetry-sdk>=1.20.0; extra == "observability"
|
|
47
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-grpc>=1.20.0; extra == "observability"
|
|
44
48
|
Provides-Extra: dev
|
|
45
49
|
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
46
50
|
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
@@ -52,7 +56,7 @@ Requires-Dist: black>=24.0.0; extra == "dev"
|
|
|
52
56
|
Requires-Dist: bandit[toml]>=1.7.0; extra == "dev"
|
|
53
57
|
Requires-Dist: numpy>=1.24.0; extra == "dev"
|
|
54
58
|
Provides-Extra: all
|
|
55
|
-
Requires-Dist: alma-memory[azure,chroma,dev,local,mcp,pinecone,postgres,qdrant]; extra == "all"
|
|
59
|
+
Requires-Dist: alma-memory[azure,chroma,dev,local,mcp,observability,pinecone,postgres,qdrant]; extra == "all"
|
|
56
60
|
|
|
57
61
|
# ALMA - Agent Learning Memory Architecture
|
|
58
62
|
|
|
@@ -79,7 +83,7 @@ ALMA isn't just another memory framework. Here's what sets it apart from alterna
|
|
|
79
83
|
| **Event System** | Webhooks + in-process callbacks | None | React to memory changes in real-time |
|
|
80
84
|
| **TypeScript SDK** | Full-featured client library | None | First-class JavaScript/TypeScript support |
|
|
81
85
|
| **Vector DB Support** | 6 backends (PostgreSQL, Qdrant, Pinecone, Chroma, SQLite, Azure) | Limited | Deploy anywhere |
|
|
82
|
-
| **Graph Memory** | Pluggable backends (Neo4j, In-memory) | Limited | Entity relationship tracking |
|
|
86
|
+
| **Graph Memory** | Pluggable backends (Neo4j, Memgraph, Kuzu, In-memory) | Limited | Entity relationship tracking |
|
|
83
87
|
| **Harness Pattern** | Decouples agent from domain memory | None | Reusable agent architecture |
|
|
84
88
|
| **MCP Integration** | Native stdio/HTTP server | None | Direct Claude Code integration |
|
|
85
89
|
| **Domain Memory Factory** | 6 pre-built schemas | None | Instant setup for any domain |
|
|
@@ -111,9 +115,16 @@ ALMA isn't just another memory framework. Here's what sets it apart from alterna
|
|
|
111
115
|
- **Graph Database Abstraction** (`alma/graph/`)
|
|
112
116
|
- Pluggable `GraphBackend` interface
|
|
113
117
|
- Neo4j backend for production
|
|
118
|
+
- Memgraph backend for high-performance in-memory graphs
|
|
119
|
+
- Kuzu backend for embedded graph storage (no server required)
|
|
114
120
|
- In-memory backend for testing
|
|
115
121
|
- Factory function `create_graph_backend()` for easy setup
|
|
116
122
|
|
|
123
|
+
- **Testing Module** (`alma/testing/`)
|
|
124
|
+
- `MockStorage` - In-memory storage backend for isolated testing
|
|
125
|
+
- `MockEmbedder` - Deterministic fake embedding provider
|
|
126
|
+
- Factory functions for creating test data with sensible defaults
|
|
127
|
+
|
|
117
128
|
### Phase 1: Core Features
|
|
118
129
|
|
|
119
130
|
- **Memory Consolidation Engine** (`alma/consolidation/`)
|
|
@@ -434,14 +445,23 @@ Capture entity relationships for complex reasoning:
|
|
|
434
445
|
```python
|
|
435
446
|
from alma.graph import create_graph_backend, BackendGraphStore, EntityExtractor
|
|
436
447
|
|
|
437
|
-
# Create graph backend
|
|
448
|
+
# Create graph backend - multiple options available:
|
|
449
|
+
|
|
450
|
+
# Neo4j (production, hosted)
|
|
438
451
|
backend = create_graph_backend(
|
|
439
452
|
"neo4j",
|
|
440
453
|
uri="neo4j+s://xxx.databases.neo4j.io",
|
|
441
454
|
username="neo4j",
|
|
442
455
|
password="your-password"
|
|
443
456
|
)
|
|
444
|
-
|
|
457
|
+
|
|
458
|
+
# Memgraph (high-performance, in-memory)
|
|
459
|
+
# backend = create_graph_backend("memgraph", uri="bolt://localhost:7687")
|
|
460
|
+
|
|
461
|
+
# Kuzu (embedded, no server required)
|
|
462
|
+
# backend = create_graph_backend("kuzu", database_path="./my_graph_db")
|
|
463
|
+
|
|
464
|
+
# In-memory (testing)
|
|
445
465
|
# backend = create_graph_backend("memory")
|
|
446
466
|
|
|
447
467
|
# Create store with backend
|
|
@@ -693,9 +713,12 @@ print(f"Recommendation: {signal.recommendation}")
|
|
|
693
713
|
| +---------------+ +------------------+ +---------------+ |
|
|
694
714
|
+-------------------------------------------------------------------------+
|
|
695
715
|
| GRAPH LAYER |
|
|
696
|
-
| +---------------+ +------------------+
|
|
697
|
-
| | Neo4j | |
|
|
698
|
-
| +---------------+ +------------------+
|
|
716
|
+
| +---------------+ +------------------+ +---------------+ |
|
|
717
|
+
| | Neo4j | | Memgraph | | Kuzu | |
|
|
718
|
+
| +---------------+ +------------------+ +---------------+ |
|
|
719
|
+
| +---------------+ |
|
|
720
|
+
| | In-Memory | |
|
|
721
|
+
| +---------------+ |
|
|
699
722
|
+-------------------------------------------------------------------------+
|
|
700
723
|
| INTEGRATION LAYER |
|
|
701
724
|
| +-------------------------------------------------------------------+ |
|
|
@@ -819,6 +842,7 @@ chroma:
|
|
|
819
842
|
| Pinecone Backend | Serverless vector DB | Done |
|
|
820
843
|
| Chroma Backend | Lightweight vector DB | Done |
|
|
821
844
|
| Graph Abstraction | Pluggable graph backends | Done |
|
|
845
|
+
| Testing Module | Mocks and factories for testing | Done |
|
|
822
846
|
|
|
823
847
|
---
|
|
824
848
|
|
|
@@ -850,6 +874,16 @@ docker run -p 6333:6333 qdrant/qdrant
|
|
|
850
874
|
- Ensure `embedding_dim` in config matches your embedding provider
|
|
851
875
|
- Local: 384, Azure text-embedding-3-small: 1536
|
|
852
876
|
|
|
877
|
+
**Memgraph connection refused**
|
|
878
|
+
```bash
|
|
879
|
+
# Start Memgraph with Docker
|
|
880
|
+
docker run -p 7687:7687 memgraph/memgraph-mage
|
|
881
|
+
```
|
|
882
|
+
|
|
883
|
+
**Kuzu database locked**
|
|
884
|
+
- Ensure only one process accesses the database at a time
|
|
885
|
+
- Use `read_only=True` for concurrent read access
|
|
886
|
+
|
|
853
887
|
### Debug Logging
|
|
854
888
|
|
|
855
889
|
```python
|
|
@@ -23,7 +23,7 @@ ALMA isn't just another memory framework. Here's what sets it apart from alterna
|
|
|
23
23
|
| **Event System** | Webhooks + in-process callbacks | None | React to memory changes in real-time |
|
|
24
24
|
| **TypeScript SDK** | Full-featured client library | None | First-class JavaScript/TypeScript support |
|
|
25
25
|
| **Vector DB Support** | 6 backends (PostgreSQL, Qdrant, Pinecone, Chroma, SQLite, Azure) | Limited | Deploy anywhere |
|
|
26
|
-
| **Graph Memory** | Pluggable backends (Neo4j, In-memory) | Limited | Entity relationship tracking |
|
|
26
|
+
| **Graph Memory** | Pluggable backends (Neo4j, Memgraph, Kuzu, In-memory) | Limited | Entity relationship tracking |
|
|
27
27
|
| **Harness Pattern** | Decouples agent from domain memory | None | Reusable agent architecture |
|
|
28
28
|
| **MCP Integration** | Native stdio/HTTP server | None | Direct Claude Code integration |
|
|
29
29
|
| **Domain Memory Factory** | 6 pre-built schemas | None | Instant setup for any domain |
|
|
@@ -55,9 +55,16 @@ ALMA isn't just another memory framework. Here's what sets it apart from alterna
|
|
|
55
55
|
- **Graph Database Abstraction** (`alma/graph/`)
|
|
56
56
|
- Pluggable `GraphBackend` interface
|
|
57
57
|
- Neo4j backend for production
|
|
58
|
+
- Memgraph backend for high-performance in-memory graphs
|
|
59
|
+
- Kuzu backend for embedded graph storage (no server required)
|
|
58
60
|
- In-memory backend for testing
|
|
59
61
|
- Factory function `create_graph_backend()` for easy setup
|
|
60
62
|
|
|
63
|
+
- **Testing Module** (`alma/testing/`)
|
|
64
|
+
- `MockStorage` - In-memory storage backend for isolated testing
|
|
65
|
+
- `MockEmbedder` - Deterministic fake embedding provider
|
|
66
|
+
- Factory functions for creating test data with sensible defaults
|
|
67
|
+
|
|
61
68
|
### Phase 1: Core Features
|
|
62
69
|
|
|
63
70
|
- **Memory Consolidation Engine** (`alma/consolidation/`)
|
|
@@ -378,14 +385,23 @@ Capture entity relationships for complex reasoning:
|
|
|
378
385
|
```python
|
|
379
386
|
from alma.graph import create_graph_backend, BackendGraphStore, EntityExtractor
|
|
380
387
|
|
|
381
|
-
# Create graph backend
|
|
388
|
+
# Create graph backend - multiple options available:
|
|
389
|
+
|
|
390
|
+
# Neo4j (production, hosted)
|
|
382
391
|
backend = create_graph_backend(
|
|
383
392
|
"neo4j",
|
|
384
393
|
uri="neo4j+s://xxx.databases.neo4j.io",
|
|
385
394
|
username="neo4j",
|
|
386
395
|
password="your-password"
|
|
387
396
|
)
|
|
388
|
-
|
|
397
|
+
|
|
398
|
+
# Memgraph (high-performance, in-memory)
|
|
399
|
+
# backend = create_graph_backend("memgraph", uri="bolt://localhost:7687")
|
|
400
|
+
|
|
401
|
+
# Kuzu (embedded, no server required)
|
|
402
|
+
# backend = create_graph_backend("kuzu", database_path="./my_graph_db")
|
|
403
|
+
|
|
404
|
+
# In-memory (testing)
|
|
389
405
|
# backend = create_graph_backend("memory")
|
|
390
406
|
|
|
391
407
|
# Create store with backend
|
|
@@ -637,9 +653,12 @@ print(f"Recommendation: {signal.recommendation}")
|
|
|
637
653
|
| +---------------+ +------------------+ +---------------+ |
|
|
638
654
|
+-------------------------------------------------------------------------+
|
|
639
655
|
| GRAPH LAYER |
|
|
640
|
-
| +---------------+ +------------------+
|
|
641
|
-
| | Neo4j | |
|
|
642
|
-
| +---------------+ +------------------+
|
|
656
|
+
| +---------------+ +------------------+ +---------------+ |
|
|
657
|
+
| | Neo4j | | Memgraph | | Kuzu | |
|
|
658
|
+
| +---------------+ +------------------+ +---------------+ |
|
|
659
|
+
| +---------------+ |
|
|
660
|
+
| | In-Memory | |
|
|
661
|
+
| +---------------+ |
|
|
643
662
|
+-------------------------------------------------------------------------+
|
|
644
663
|
| INTEGRATION LAYER |
|
|
645
664
|
| +-------------------------------------------------------------------+ |
|
|
@@ -763,6 +782,7 @@ chroma:
|
|
|
763
782
|
| Pinecone Backend | Serverless vector DB | Done |
|
|
764
783
|
| Chroma Backend | Lightweight vector DB | Done |
|
|
765
784
|
| Graph Abstraction | Pluggable graph backends | Done |
|
|
785
|
+
| Testing Module | Mocks and factories for testing | Done |
|
|
766
786
|
|
|
767
787
|
---
|
|
768
788
|
|
|
@@ -794,6 +814,16 @@ docker run -p 6333:6333 qdrant/qdrant
|
|
|
794
814
|
- Ensure `embedding_dim` in config matches your embedding provider
|
|
795
815
|
- Local: 384, Azure text-embedding-3-small: 1536
|
|
796
816
|
|
|
817
|
+
**Memgraph connection refused**
|
|
818
|
+
```bash
|
|
819
|
+
# Start Memgraph with Docker
|
|
820
|
+
docker run -p 7687:7687 memgraph/memgraph-mage
|
|
821
|
+
```
|
|
822
|
+
|
|
823
|
+
**Kuzu database locked**
|
|
824
|
+
- Ensure only one process accesses the database at a time
|
|
825
|
+
- Use `read_only=True` for concurrent read access
|
|
826
|
+
|
|
797
827
|
### Debug Logging
|
|
798
828
|
|
|
799
829
|
```python
|
|
@@ -12,9 +12,24 @@ The Harness Pattern:
|
|
|
12
12
|
|
|
13
13
|
This makes any tool-using agent appear to "learn" by injecting relevant
|
|
14
14
|
memory slices before each run and updating memory after.
|
|
15
|
+
|
|
16
|
+
Testing Support:
|
|
17
|
+
For testing ALMA integrations, use the `alma.testing` module:
|
|
18
|
+
|
|
19
|
+
from alma.testing import MockStorage, create_test_heuristic
|
|
20
|
+
|
|
21
|
+
def test_my_integration():
|
|
22
|
+
storage = MockStorage()
|
|
23
|
+
heuristic = create_test_heuristic(agent="test-agent")
|
|
24
|
+
storage.save_heuristic(heuristic)
|
|
25
|
+
|
|
26
|
+
Available utilities:
|
|
27
|
+
- MockStorage: In-memory storage backend
|
|
28
|
+
- MockEmbedder: Deterministic fake embeddings
|
|
29
|
+
- create_test_heuristic(), create_test_outcome(), etc.
|
|
15
30
|
"""
|
|
16
31
|
|
|
17
|
-
__version__ = "0.
|
|
32
|
+
__version__ = "0.5.1"
|
|
18
33
|
|
|
19
34
|
# Core
|
|
20
35
|
# Confidence Engine (Phase 12)
|
|
@@ -92,6 +107,16 @@ from alma.initializer import (
|
|
|
92
107
|
SessionInitializer,
|
|
93
108
|
)
|
|
94
109
|
|
|
110
|
+
# Observability (Phase 20)
|
|
111
|
+
from alma.observability import (
|
|
112
|
+
ALMAMetrics,
|
|
113
|
+
configure_observability,
|
|
114
|
+
get_logger,
|
|
115
|
+
get_metrics,
|
|
116
|
+
get_tracer,
|
|
117
|
+
trace_method,
|
|
118
|
+
)
|
|
119
|
+
|
|
95
120
|
# Progress Tracking (Phase 10)
|
|
96
121
|
from alma.progress import (
|
|
97
122
|
ProgressLog,
|
|
@@ -191,4 +216,11 @@ __all__ = [
|
|
|
191
216
|
"EmbeddingError",
|
|
192
217
|
"RetrievalError",
|
|
193
218
|
"ExtractionError",
|
|
219
|
+
# Observability
|
|
220
|
+
"configure_observability",
|
|
221
|
+
"get_tracer",
|
|
222
|
+
"get_logger",
|
|
223
|
+
"get_metrics",
|
|
224
|
+
"ALMAMetrics",
|
|
225
|
+
"trace_method",
|
|
194
226
|
]
|
|
@@ -1,22 +1,38 @@
|
|
|
1
1
|
"""
|
|
2
2
|
ALMA Core - Main interface for the Agent Learning Memory Architecture.
|
|
3
|
+
|
|
4
|
+
API Return Type Conventions:
|
|
5
|
+
- Create operations: Return created object or raise exception
|
|
6
|
+
- Update operations: Return updated object or raise exception
|
|
7
|
+
- Delete operations: Return bool (success) or int (count), raise on failure
|
|
8
|
+
- Query operations: Return list (empty if none) or object
|
|
9
|
+
|
|
10
|
+
All scope violations raise ScopeViolationError for consistent error handling.
|
|
3
11
|
"""
|
|
4
12
|
|
|
5
13
|
import logging
|
|
14
|
+
import time
|
|
6
15
|
from typing import Any, Dict, Optional
|
|
7
16
|
|
|
8
17
|
from alma.config.loader import ConfigLoader
|
|
18
|
+
from alma.exceptions import ScopeViolationError
|
|
9
19
|
from alma.learning.protocols import LearningProtocol
|
|
20
|
+
from alma.observability.logging import get_logger
|
|
21
|
+
from alma.observability.metrics import get_metrics
|
|
22
|
+
from alma.observability.tracing import SpanKind, get_tracer, trace_method
|
|
10
23
|
from alma.retrieval.engine import RetrievalEngine
|
|
11
24
|
from alma.storage.base import StorageBackend
|
|
12
25
|
from alma.types import (
|
|
13
26
|
DomainKnowledge,
|
|
14
27
|
MemoryScope,
|
|
15
28
|
MemorySlice,
|
|
29
|
+
Outcome,
|
|
16
30
|
UserPreference,
|
|
17
31
|
)
|
|
18
32
|
|
|
19
33
|
logger = logging.getLogger(__name__)
|
|
34
|
+
structured_logger = get_logger(__name__)
|
|
35
|
+
tracer = get_tracer(__name__)
|
|
20
36
|
|
|
21
37
|
|
|
22
38
|
class ALMA:
|
|
@@ -124,6 +140,7 @@ class ALMA:
|
|
|
124
140
|
|
|
125
141
|
return FileBasedStorage.from_config(config)
|
|
126
142
|
|
|
143
|
+
@trace_method(name="ALMA.retrieve", kind=SpanKind.INTERNAL)
|
|
127
144
|
def retrieve(
|
|
128
145
|
self,
|
|
129
146
|
task: str,
|
|
@@ -143,11 +160,19 @@ class ALMA:
|
|
|
143
160
|
Returns:
|
|
144
161
|
MemorySlice with relevant memories for context injection
|
|
145
162
|
"""
|
|
163
|
+
start_time = time.time()
|
|
164
|
+
metrics = get_metrics()
|
|
165
|
+
|
|
146
166
|
# Validate agent has a defined scope
|
|
147
167
|
if agent not in self.scopes:
|
|
148
168
|
logger.warning(f"Agent '{agent}' has no defined scope, using defaults")
|
|
169
|
+
structured_logger.warning(
|
|
170
|
+
"Agent has no defined scope, using defaults",
|
|
171
|
+
agent=agent,
|
|
172
|
+
project_id=self.project_id,
|
|
173
|
+
)
|
|
149
174
|
|
|
150
|
-
|
|
175
|
+
result = self.retrieval.retrieve(
|
|
151
176
|
query=task,
|
|
152
177
|
agent=agent,
|
|
153
178
|
project_id=self.project_id,
|
|
@@ -156,6 +181,30 @@ class ALMA:
|
|
|
156
181
|
scope=self.scopes.get(agent),
|
|
157
182
|
)
|
|
158
183
|
|
|
184
|
+
# Record metrics
|
|
185
|
+
duration_ms = (time.time() - start_time) * 1000
|
|
186
|
+
cache_hit = result.retrieval_time_ms < 10 # Approximate cache hit detection
|
|
187
|
+
metrics.record_retrieve_latency(
|
|
188
|
+
duration_ms=duration_ms,
|
|
189
|
+
agent=agent,
|
|
190
|
+
project_id=self.project_id,
|
|
191
|
+
cache_hit=cache_hit,
|
|
192
|
+
items_returned=result.total_items,
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
structured_logger.info(
|
|
196
|
+
"Memory retrieval completed",
|
|
197
|
+
agent=agent,
|
|
198
|
+
project_id=self.project_id,
|
|
199
|
+
task_preview=task[:50] if task else "",
|
|
200
|
+
items_returned=result.total_items,
|
|
201
|
+
duration_ms=duration_ms,
|
|
202
|
+
cache_hit=cache_hit,
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
return result
|
|
206
|
+
|
|
207
|
+
@trace_method(name="ALMA.learn", kind=SpanKind.INTERNAL)
|
|
159
208
|
def learn(
|
|
160
209
|
self,
|
|
161
210
|
agent: str,
|
|
@@ -166,7 +215,7 @@ class ALMA:
|
|
|
166
215
|
duration_ms: Optional[int] = None,
|
|
167
216
|
error_message: Optional[str] = None,
|
|
168
217
|
feedback: Optional[str] = None,
|
|
169
|
-
) ->
|
|
218
|
+
) -> Outcome:
|
|
170
219
|
"""
|
|
171
220
|
Learn from a task outcome.
|
|
172
221
|
|
|
@@ -184,9 +233,15 @@ class ALMA:
|
|
|
184
233
|
feedback: User feedback if provided
|
|
185
234
|
|
|
186
235
|
Returns:
|
|
187
|
-
|
|
236
|
+
The created Outcome record
|
|
237
|
+
|
|
238
|
+
Raises:
|
|
239
|
+
ScopeViolationError: If learning is outside agent's scope
|
|
188
240
|
"""
|
|
189
|
-
|
|
241
|
+
start_time = time.time()
|
|
242
|
+
metrics = get_metrics()
|
|
243
|
+
|
|
244
|
+
outcome_record = self.learning.learn(
|
|
190
245
|
agent=agent,
|
|
191
246
|
project_id=self.project_id,
|
|
192
247
|
task=task,
|
|
@@ -199,10 +254,28 @@ class ALMA:
|
|
|
199
254
|
)
|
|
200
255
|
|
|
201
256
|
# Invalidate cache for this agent/project after learning
|
|
202
|
-
|
|
203
|
-
self.retrieval.invalidate_cache(agent=agent, project_id=self.project_id)
|
|
257
|
+
self.retrieval.invalidate_cache(agent=agent, project_id=self.project_id)
|
|
204
258
|
|
|
205
|
-
|
|
259
|
+
# Record metrics
|
|
260
|
+
learn_duration_ms = (time.time() - start_time) * 1000
|
|
261
|
+
metrics.record_learn_operation(
|
|
262
|
+
duration_ms=learn_duration_ms,
|
|
263
|
+
agent=agent,
|
|
264
|
+
project_id=self.project_id,
|
|
265
|
+
memory_type="outcome",
|
|
266
|
+
success=True,
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
structured_logger.info(
|
|
270
|
+
"Learning operation completed",
|
|
271
|
+
agent=agent,
|
|
272
|
+
project_id=self.project_id,
|
|
273
|
+
task_type=task_type,
|
|
274
|
+
outcome=outcome,
|
|
275
|
+
duration_ms=learn_duration_ms,
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
return outcome_record
|
|
206
279
|
|
|
207
280
|
def add_user_preference(
|
|
208
281
|
self,
|
|
@@ -241,7 +314,7 @@ class ALMA:
|
|
|
241
314
|
domain: str,
|
|
242
315
|
fact: str,
|
|
243
316
|
source: str = "user_stated",
|
|
244
|
-
) ->
|
|
317
|
+
) -> DomainKnowledge:
|
|
245
318
|
"""
|
|
246
319
|
Add domain knowledge within agent's scope.
|
|
247
320
|
|
|
@@ -252,13 +325,17 @@ class ALMA:
|
|
|
252
325
|
source: How this was learned
|
|
253
326
|
|
|
254
327
|
Returns:
|
|
255
|
-
The created DomainKnowledge
|
|
328
|
+
The created DomainKnowledge
|
|
329
|
+
|
|
330
|
+
Raises:
|
|
331
|
+
ScopeViolationError: If agent is not allowed to learn in this domain
|
|
256
332
|
"""
|
|
257
333
|
# Check scope
|
|
258
334
|
scope = self.scopes.get(agent)
|
|
259
335
|
if scope and not scope.is_allowed(domain):
|
|
260
|
-
|
|
261
|
-
|
|
336
|
+
raise ScopeViolationError(
|
|
337
|
+
f"Agent '{agent}' is not allowed to learn in domain '{domain}'"
|
|
338
|
+
)
|
|
262
339
|
|
|
263
340
|
result = self.learning.add_domain_knowledge(
|
|
264
341
|
agent=agent,
|
|
@@ -269,11 +346,11 @@ class ALMA:
|
|
|
269
346
|
)
|
|
270
347
|
|
|
271
348
|
# Invalidate cache for this agent/project after adding knowledge
|
|
272
|
-
|
|
273
|
-
self.retrieval.invalidate_cache(agent=agent, project_id=self.project_id)
|
|
349
|
+
self.retrieval.invalidate_cache(agent=agent, project_id=self.project_id)
|
|
274
350
|
|
|
275
351
|
return result
|
|
276
352
|
|
|
353
|
+
@trace_method(name="ALMA.forget", kind=SpanKind.INTERNAL)
|
|
277
354
|
def forget(
|
|
278
355
|
self,
|
|
279
356
|
agent: Optional[str] = None,
|
|
@@ -283,7 +360,8 @@ class ALMA:
|
|
|
283
360
|
"""
|
|
284
361
|
Prune stale or low-confidence memories.
|
|
285
362
|
|
|
286
|
-
|
|
363
|
+
This is a delete operation that invalidates cache after pruning
|
|
364
|
+
to ensure fresh retrieval results.
|
|
287
365
|
|
|
288
366
|
Args:
|
|
289
367
|
agent: Specific agent to prune, or None for all
|
|
@@ -291,8 +369,14 @@ class ALMA:
|
|
|
291
369
|
below_confidence: Remove heuristics below this confidence
|
|
292
370
|
|
|
293
371
|
Returns:
|
|
294
|
-
Number of items pruned
|
|
372
|
+
Number of items pruned (0 if nothing was pruned)
|
|
373
|
+
|
|
374
|
+
Raises:
|
|
375
|
+
StorageError: If the delete operation fails
|
|
295
376
|
"""
|
|
377
|
+
start_time = time.time()
|
|
378
|
+
metrics = get_metrics()
|
|
379
|
+
|
|
296
380
|
count = self.learning.forget(
|
|
297
381
|
project_id=self.project_id,
|
|
298
382
|
agent=agent,
|
|
@@ -304,17 +388,41 @@ class ALMA:
|
|
|
304
388
|
if count > 0:
|
|
305
389
|
self.retrieval.invalidate_cache(agent=agent, project_id=self.project_id)
|
|
306
390
|
|
|
391
|
+
# Record metrics
|
|
392
|
+
duration_ms = (time.time() - start_time) * 1000
|
|
393
|
+
metrics.record_forget_operation(
|
|
394
|
+
duration_ms=duration_ms,
|
|
395
|
+
agent=agent,
|
|
396
|
+
project_id=self.project_id,
|
|
397
|
+
items_removed=count,
|
|
398
|
+
)
|
|
399
|
+
|
|
400
|
+
structured_logger.info(
|
|
401
|
+
"Forget operation completed",
|
|
402
|
+
agent=agent or "all",
|
|
403
|
+
project_id=self.project_id,
|
|
404
|
+
items_removed=count,
|
|
405
|
+
older_than_days=older_than_days,
|
|
406
|
+
below_confidence=below_confidence,
|
|
407
|
+
duration_ms=duration_ms,
|
|
408
|
+
)
|
|
409
|
+
|
|
307
410
|
return count
|
|
308
411
|
|
|
309
412
|
def get_stats(self, agent: Optional[str] = None) -> Dict[str, Any]:
|
|
310
413
|
"""
|
|
311
414
|
Get memory statistics.
|
|
312
415
|
|
|
416
|
+
This is a query operation that returns statistics about stored memories.
|
|
417
|
+
|
|
313
418
|
Args:
|
|
314
419
|
agent: Specific agent or None for all
|
|
315
420
|
|
|
316
421
|
Returns:
|
|
317
|
-
Dict with counts and metadata
|
|
422
|
+
Dict with counts and metadata (always returns a dict, may be empty)
|
|
423
|
+
|
|
424
|
+
Raises:
|
|
425
|
+
StorageError: If the query operation fails
|
|
318
426
|
"""
|
|
319
427
|
return self.storage.get_stats(
|
|
320
428
|
project_id=self.project_id,
|
|
@@ -208,16 +208,17 @@ class AutoLearner:
|
|
|
208
208
|
preference=fact.content,
|
|
209
209
|
source="auto_extraction",
|
|
210
210
|
)
|
|
211
|
-
return pref.id
|
|
211
|
+
return pref.id
|
|
212
212
|
|
|
213
213
|
elif fact.fact_type == FactType.DOMAIN_KNOWLEDGE:
|
|
214
|
+
# add_domain_knowledge now raises ScopeViolationError instead of returning None
|
|
214
215
|
knowledge = self.alma.add_domain_knowledge(
|
|
215
216
|
agent=agent,
|
|
216
217
|
domain=fact.domain or "general",
|
|
217
218
|
fact=fact.content,
|
|
218
219
|
source="auto_extraction",
|
|
219
220
|
)
|
|
220
|
-
return knowledge.id
|
|
221
|
+
return knowledge.id
|
|
221
222
|
|
|
222
223
|
elif fact.fact_type == FactType.OUTCOME:
|
|
223
224
|
# Outcomes need success/failure info we don't have
|
|
@@ -228,7 +229,7 @@ class AutoLearner:
|
|
|
228
229
|
fact=fact.content,
|
|
229
230
|
source="auto_extraction",
|
|
230
231
|
)
|
|
231
|
-
return knowledge.id
|
|
232
|
+
return knowledge.id
|
|
232
233
|
|
|
233
234
|
return None
|
|
234
235
|
|
|
@@ -48,7 +48,7 @@ def create_graph_backend(backend: str = "neo4j", **config) -> GraphBackend:
|
|
|
48
48
|
Factory function to create a graph backend.
|
|
49
49
|
|
|
50
50
|
Args:
|
|
51
|
-
backend: Backend type ("neo4j" or "memory")
|
|
51
|
+
backend: Backend type ("neo4j", "memgraph", "kuzu", or "memory")
|
|
52
52
|
**config: Backend-specific configuration options
|
|
53
53
|
|
|
54
54
|
Returns:
|
|
@@ -66,6 +66,23 @@ def create_graph_backend(backend: str = "neo4j", **config) -> GraphBackend:
|
|
|
66
66
|
password="password"
|
|
67
67
|
)
|
|
68
68
|
|
|
69
|
+
# Create Memgraph backend
|
|
70
|
+
backend = create_graph_backend(
|
|
71
|
+
backend="memgraph",
|
|
72
|
+
uri="bolt://localhost:7687",
|
|
73
|
+
username="",
|
|
74
|
+
password=""
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
# Create Kuzu embedded backend (persistent)
|
|
78
|
+
backend = create_graph_backend(
|
|
79
|
+
backend="kuzu",
|
|
80
|
+
database_path="./my_graph_db"
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
# Create Kuzu embedded backend (in-memory)
|
|
84
|
+
backend = create_graph_backend(backend="kuzu")
|
|
85
|
+
|
|
69
86
|
# Create in-memory backend for testing
|
|
70
87
|
backend = create_graph_backend(backend="memory")
|
|
71
88
|
"""
|
|
@@ -73,6 +90,14 @@ def create_graph_backend(backend: str = "neo4j", **config) -> GraphBackend:
|
|
|
73
90
|
from alma.graph.backends.neo4j import Neo4jBackend
|
|
74
91
|
|
|
75
92
|
return Neo4jBackend(**config)
|
|
93
|
+
elif backend == "memgraph":
|
|
94
|
+
from alma.graph.backends.memgraph import MemgraphBackend
|
|
95
|
+
|
|
96
|
+
return MemgraphBackend(**config)
|
|
97
|
+
elif backend == "kuzu":
|
|
98
|
+
from alma.graph.backends.kuzu import KuzuBackend
|
|
99
|
+
|
|
100
|
+
return KuzuBackend(**config)
|
|
76
101
|
elif backend == "memory":
|
|
77
102
|
from alma.graph.backends.memory import InMemoryBackend
|
|
78
103
|
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ALMA Graph Memory Backends.
|
|
3
|
+
|
|
4
|
+
This package contains implementations of the GraphBackend interface
|
|
5
|
+
for various graph database systems.
|
|
6
|
+
|
|
7
|
+
Available backends:
|
|
8
|
+
- neo4j: Neo4j graph database backend
|
|
9
|
+
- memgraph: Memgraph graph database backend (Neo4j Bolt protocol compatible)
|
|
10
|
+
- kuzu: Kuzu embedded graph database backend (no server required)
|
|
11
|
+
- memory: In-memory backend for testing and development
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from alma.graph.backends.memgraph import MemgraphBackend
|
|
15
|
+
from alma.graph.backends.memory import InMemoryBackend
|
|
16
|
+
from alma.graph.backends.neo4j import Neo4jBackend
|
|
17
|
+
|
|
18
|
+
# Kuzu is an optional dependency
|
|
19
|
+
try:
|
|
20
|
+
from alma.graph.backends.kuzu import KuzuBackend
|
|
21
|
+
|
|
22
|
+
_KUZU_AVAILABLE = True
|
|
23
|
+
except ImportError:
|
|
24
|
+
KuzuBackend = None # type: ignore
|
|
25
|
+
_KUZU_AVAILABLE = False
|
|
26
|
+
|
|
27
|
+
__all__ = [
|
|
28
|
+
"Neo4jBackend",
|
|
29
|
+
"MemgraphBackend",
|
|
30
|
+
"KuzuBackend",
|
|
31
|
+
"InMemoryBackend",
|
|
32
|
+
]
|