alma-memory 0.2.0__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.
- alma/__init__.py +75 -0
- alma/config/__init__.py +5 -0
- alma/config/loader.py +156 -0
- alma/core.py +322 -0
- alma/harness/__init__.py +35 -0
- alma/harness/base.py +377 -0
- alma/harness/domains.py +689 -0
- alma/integration/__init__.py +62 -0
- alma/integration/claude_agents.py +432 -0
- alma/integration/helena.py +413 -0
- alma/integration/victor.py +447 -0
- alma/learning/__init__.py +86 -0
- alma/learning/forgetting.py +1396 -0
- alma/learning/heuristic_extractor.py +374 -0
- alma/learning/protocols.py +326 -0
- alma/learning/validation.py +341 -0
- alma/mcp/__init__.py +45 -0
- alma/mcp/__main__.py +155 -0
- alma/mcp/resources.py +121 -0
- alma/mcp/server.py +533 -0
- alma/mcp/tools.py +374 -0
- alma/retrieval/__init__.py +53 -0
- alma/retrieval/cache.py +1062 -0
- alma/retrieval/embeddings.py +202 -0
- alma/retrieval/engine.py +287 -0
- alma/retrieval/scoring.py +334 -0
- alma/storage/__init__.py +20 -0
- alma/storage/azure_cosmos.py +972 -0
- alma/storage/base.py +372 -0
- alma/storage/file_based.py +583 -0
- alma/storage/sqlite_local.py +912 -0
- alma/types.py +216 -0
- alma_memory-0.2.0.dist-info/METADATA +327 -0
- alma_memory-0.2.0.dist-info/RECORD +36 -0
- alma_memory-0.2.0.dist-info/WHEEL +5 -0
- alma_memory-0.2.0.dist-info/top_level.txt +1 -0
alma/types.py
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ALMA Memory Types
|
|
3
|
+
|
|
4
|
+
Defines the core data structures for all memory types.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from dataclasses import dataclass, field
|
|
8
|
+
from datetime import datetime
|
|
9
|
+
from typing import Optional, List, Dict, Any
|
|
10
|
+
from enum import Enum
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class MemoryType(Enum):
|
|
14
|
+
"""Categories of memory that agents can store and retrieve."""
|
|
15
|
+
HEURISTIC = "heuristic"
|
|
16
|
+
OUTCOME = "outcome"
|
|
17
|
+
USER_PREFERENCE = "user_preference"
|
|
18
|
+
DOMAIN_KNOWLEDGE = "domain_knowledge"
|
|
19
|
+
ANTI_PATTERN = "anti_pattern"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclass
|
|
23
|
+
class MemoryScope:
|
|
24
|
+
"""
|
|
25
|
+
Defines what an agent is allowed to learn.
|
|
26
|
+
|
|
27
|
+
Prevents scope creep by explicitly listing allowed and forbidden domains.
|
|
28
|
+
"""
|
|
29
|
+
agent_name: str
|
|
30
|
+
can_learn: List[str]
|
|
31
|
+
cannot_learn: List[str]
|
|
32
|
+
min_occurrences_for_heuristic: int = 3
|
|
33
|
+
|
|
34
|
+
def is_allowed(self, domain: str) -> bool:
|
|
35
|
+
"""Check if learning in this domain is permitted."""
|
|
36
|
+
if domain in self.cannot_learn:
|
|
37
|
+
return False
|
|
38
|
+
if not self.can_learn: # Empty means all allowed (except cannot_learn)
|
|
39
|
+
return True
|
|
40
|
+
return domain in self.can_learn
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@dataclass
|
|
44
|
+
class Heuristic:
|
|
45
|
+
"""
|
|
46
|
+
A learned rule: "When condition X, strategy Y works N% of the time."
|
|
47
|
+
|
|
48
|
+
Heuristics are only created after min_occurrences validations.
|
|
49
|
+
"""
|
|
50
|
+
id: str
|
|
51
|
+
agent: str
|
|
52
|
+
project_id: str
|
|
53
|
+
condition: str # "form with multiple required fields"
|
|
54
|
+
strategy: str # "test happy path first, then individual validation"
|
|
55
|
+
confidence: float # 0.0 to 1.0
|
|
56
|
+
occurrence_count: int
|
|
57
|
+
success_count: int
|
|
58
|
+
last_validated: datetime
|
|
59
|
+
created_at: datetime
|
|
60
|
+
embedding: Optional[List[float]] = None
|
|
61
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
62
|
+
|
|
63
|
+
@property
|
|
64
|
+
def success_rate(self) -> float:
|
|
65
|
+
"""Calculate success rate from occurrences."""
|
|
66
|
+
if self.occurrence_count == 0:
|
|
67
|
+
return 0.0
|
|
68
|
+
return self.success_count / self.occurrence_count
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@dataclass
|
|
72
|
+
class Outcome:
|
|
73
|
+
"""
|
|
74
|
+
Record of a task execution - success or failure with context.
|
|
75
|
+
|
|
76
|
+
Outcomes are raw data that can be consolidated into heuristics.
|
|
77
|
+
"""
|
|
78
|
+
id: str
|
|
79
|
+
agent: str
|
|
80
|
+
project_id: str
|
|
81
|
+
task_type: str # "api_validation", "form_testing", etc.
|
|
82
|
+
task_description: str
|
|
83
|
+
success: bool
|
|
84
|
+
strategy_used: str
|
|
85
|
+
duration_ms: Optional[int] = None
|
|
86
|
+
error_message: Optional[str] = None
|
|
87
|
+
user_feedback: Optional[str] = None
|
|
88
|
+
timestamp: datetime = field(default_factory=datetime.utcnow)
|
|
89
|
+
embedding: Optional[List[float]] = None
|
|
90
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@dataclass
|
|
94
|
+
class UserPreference:
|
|
95
|
+
"""
|
|
96
|
+
A remembered user constraint or communication preference.
|
|
97
|
+
|
|
98
|
+
Persists across sessions so users don't repeat themselves.
|
|
99
|
+
"""
|
|
100
|
+
id: str
|
|
101
|
+
user_id: str
|
|
102
|
+
category: str # "communication", "code_style", "workflow"
|
|
103
|
+
preference: str # "No emojis in documentation"
|
|
104
|
+
source: str # "explicit_instruction", "inferred_from_correction"
|
|
105
|
+
confidence: float = 1.0 # Lower for inferred preferences
|
|
106
|
+
timestamp: datetime = field(default_factory=datetime.utcnow)
|
|
107
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
@dataclass
|
|
111
|
+
class DomainKnowledge:
|
|
112
|
+
"""
|
|
113
|
+
Accumulated domain-specific facts within agent's scope.
|
|
114
|
+
|
|
115
|
+
Different from heuristics - these are facts, not strategies.
|
|
116
|
+
"""
|
|
117
|
+
id: str
|
|
118
|
+
agent: str
|
|
119
|
+
project_id: str
|
|
120
|
+
domain: str # "authentication", "database_schema", etc.
|
|
121
|
+
fact: str # "Login endpoint uses JWT with 24h expiry"
|
|
122
|
+
source: str # "code_analysis", "documentation", "user_stated"
|
|
123
|
+
confidence: float = 1.0
|
|
124
|
+
last_verified: datetime = field(default_factory=datetime.utcnow)
|
|
125
|
+
embedding: Optional[List[float]] = None
|
|
126
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
@dataclass
|
|
130
|
+
class AntiPattern:
|
|
131
|
+
"""
|
|
132
|
+
What NOT to do - learned from validated failures.
|
|
133
|
+
|
|
134
|
+
Helps agents avoid repeating mistakes.
|
|
135
|
+
"""
|
|
136
|
+
id: str
|
|
137
|
+
agent: str
|
|
138
|
+
project_id: str
|
|
139
|
+
pattern: str # "Using fixed sleep() for async waits"
|
|
140
|
+
why_bad: str # "Causes flaky tests, doesn't adapt to load"
|
|
141
|
+
better_alternative: str # "Use explicit waits with conditions"
|
|
142
|
+
occurrence_count: int
|
|
143
|
+
last_seen: datetime
|
|
144
|
+
created_at: datetime = field(default_factory=datetime.utcnow)
|
|
145
|
+
embedding: Optional[List[float]] = None
|
|
146
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
@dataclass
|
|
150
|
+
class MemorySlice:
|
|
151
|
+
"""
|
|
152
|
+
A compact, relevant subset of memories for injection into context.
|
|
153
|
+
|
|
154
|
+
This is what gets injected per-call - must stay under token budget.
|
|
155
|
+
"""
|
|
156
|
+
heuristics: List[Heuristic] = field(default_factory=list)
|
|
157
|
+
outcomes: List[Outcome] = field(default_factory=list)
|
|
158
|
+
preferences: List[UserPreference] = field(default_factory=list)
|
|
159
|
+
domain_knowledge: List[DomainKnowledge] = field(default_factory=list)
|
|
160
|
+
anti_patterns: List[AntiPattern] = field(default_factory=list)
|
|
161
|
+
|
|
162
|
+
# Retrieval metadata
|
|
163
|
+
query: Optional[str] = None
|
|
164
|
+
agent: Optional[str] = None
|
|
165
|
+
retrieval_time_ms: Optional[int] = None
|
|
166
|
+
|
|
167
|
+
def to_prompt(self, max_tokens: int = 2000) -> str:
|
|
168
|
+
"""
|
|
169
|
+
Format memories for injection into agent context.
|
|
170
|
+
|
|
171
|
+
Respects token budget by prioritizing high-confidence items.
|
|
172
|
+
"""
|
|
173
|
+
sections = []
|
|
174
|
+
|
|
175
|
+
if self.heuristics:
|
|
176
|
+
h_text = "## Relevant Strategies\n"
|
|
177
|
+
for h in sorted(self.heuristics, key=lambda x: -x.confidence)[:5]:
|
|
178
|
+
h_text += f"- When: {h.condition}\n Do: {h.strategy} (confidence: {h.confidence:.0%})\n"
|
|
179
|
+
sections.append(h_text)
|
|
180
|
+
|
|
181
|
+
if self.anti_patterns:
|
|
182
|
+
ap_text = "## Avoid These Patterns\n"
|
|
183
|
+
for ap in self.anti_patterns[:3]:
|
|
184
|
+
ap_text += f"- Don't: {ap.pattern}\n Why: {ap.why_bad}\n Instead: {ap.better_alternative}\n"
|
|
185
|
+
sections.append(ap_text)
|
|
186
|
+
|
|
187
|
+
if self.preferences:
|
|
188
|
+
p_text = "## User Preferences\n"
|
|
189
|
+
for p in self.preferences[:5]:
|
|
190
|
+
p_text += f"- {p.preference}\n"
|
|
191
|
+
sections.append(p_text)
|
|
192
|
+
|
|
193
|
+
if self.domain_knowledge:
|
|
194
|
+
dk_text = "## Domain Context\n"
|
|
195
|
+
for dk in self.domain_knowledge[:5]:
|
|
196
|
+
dk_text += f"- {dk.fact}\n"
|
|
197
|
+
sections.append(dk_text)
|
|
198
|
+
|
|
199
|
+
result = "\n".join(sections)
|
|
200
|
+
|
|
201
|
+
# Basic token estimation (rough: 1 token ~ 4 chars)
|
|
202
|
+
if len(result) > max_tokens * 4:
|
|
203
|
+
result = result[:max_tokens * 4] + "\n[truncated]"
|
|
204
|
+
|
|
205
|
+
return result
|
|
206
|
+
|
|
207
|
+
@property
|
|
208
|
+
def total_items(self) -> int:
|
|
209
|
+
"""Total number of memory items in this slice."""
|
|
210
|
+
return (
|
|
211
|
+
len(self.heuristics) +
|
|
212
|
+
len(self.outcomes) +
|
|
213
|
+
len(self.preferences) +
|
|
214
|
+
len(self.domain_knowledge) +
|
|
215
|
+
len(self.anti_patterns)
|
|
216
|
+
)
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: alma-memory
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Agent Learning Memory Architecture - Persistent memory for AI agents
|
|
5
|
+
Author-email: RBKunnela <aiagentsprompt@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/RBKunnela/ALMA-memory
|
|
8
|
+
Project-URL: Documentation, https://github.com/RBKunnela/ALMA-memory/tree/main/docs
|
|
9
|
+
Project-URL: Repository, https://github.com/RBKunnela/ALMA-memory
|
|
10
|
+
Project-URL: Issues, https://github.com/RBKunnela/ALMA-memory/issues
|
|
11
|
+
Keywords: ai,agents,memory,learning,llm,azure,claude
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
Requires-Dist: pyyaml>=6.0
|
|
23
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
24
|
+
Provides-Extra: local
|
|
25
|
+
Requires-Dist: sentence-transformers>=2.2.0; extra == "local"
|
|
26
|
+
Requires-Dist: faiss-cpu>=1.7.4; extra == "local"
|
|
27
|
+
Provides-Extra: azure
|
|
28
|
+
Requires-Dist: azure-cosmos>=4.5.0; extra == "azure"
|
|
29
|
+
Requires-Dist: azure-identity>=1.15.0; extra == "azure"
|
|
30
|
+
Requires-Dist: azure-keyvault-secrets>=4.7.0; extra == "azure"
|
|
31
|
+
Requires-Dist: openai>=1.0.0; extra == "azure"
|
|
32
|
+
Provides-Extra: mcp
|
|
33
|
+
Requires-Dist: pydantic>=2.0.0; extra == "mcp"
|
|
34
|
+
Requires-Dist: aiohttp>=3.9.0; extra == "mcp"
|
|
35
|
+
Provides-Extra: dev
|
|
36
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
37
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
38
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
39
|
+
Requires-Dist: pytest-benchmark>=4.0.0; extra == "dev"
|
|
40
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
41
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
42
|
+
Provides-Extra: all
|
|
43
|
+
Requires-Dist: alma-memory[azure,dev,local,mcp]; extra == "all"
|
|
44
|
+
|
|
45
|
+
# ALMA - Agent Learning Memory Architecture
|
|
46
|
+
|
|
47
|
+
> A reusable harness pattern for creating AI agents that learn and improve over time through structured memory - without model weight updates.
|
|
48
|
+
|
|
49
|
+
## The Harness Pattern
|
|
50
|
+
|
|
51
|
+
ALMA isn't just agent memory - it's a **generalized framework** for any tool-using workflow:
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
55
|
+
│ 1. SETTING Fixed environment: tools, constraints │
|
|
56
|
+
├─────────────────────────────────────────────────────────────────┤
|
|
57
|
+
│ 2. CONTEXT Ephemeral per-run inputs: task, user │
|
|
58
|
+
├─────────────────────────────────────────────────────────────────┤
|
|
59
|
+
│ 3. AGENT The executor with scoped intelligence │
|
|
60
|
+
├─────────────────────────────────────────────────────────────────┤
|
|
61
|
+
│ 4. MEMORY SCHEMA Domain-specific learning structure │
|
|
62
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**The Flow:**
|
|
66
|
+
1. **Pre-run**: Inject relevant memory slices ("Past successes in similar tasks")
|
|
67
|
+
2. **Run**: Agent acts using tools, logs reflections
|
|
68
|
+
3. **Post-run**: Update memory schema
|
|
69
|
+
4. **Repeat**: Agent appears to "learn" without weight changes
|
|
70
|
+
|
|
71
|
+
## Why This Matters
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
Code exists ≠ Knowledge retained
|
|
75
|
+
Knowledge retained ≠ Knowledge scoped
|
|
76
|
+
Knowledge scoped ≠ Knowledge retrieved efficiently
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
ALMA solves all three through **scoped memory injection**. Agents get smarter via better-informed prompts, not model changes.
|
|
80
|
+
|
|
81
|
+
## Supported Domains
|
|
82
|
+
|
|
83
|
+
ALMA works for ANY tool-using workflow:
|
|
84
|
+
|
|
85
|
+
| Domain | Agents | Use Case |
|
|
86
|
+
|--------|--------|----------|
|
|
87
|
+
| **Coding** | Helena, Victor | Testing, API development |
|
|
88
|
+
| **Research** | Researcher | Market analysis, competitive intelligence |
|
|
89
|
+
| **Content** | Copywriter, Documenter | Marketing, documentation |
|
|
90
|
+
| **Operations** | Support | Customer service, automation |
|
|
91
|
+
|
|
92
|
+
## Quick Start
|
|
93
|
+
|
|
94
|
+
### Installation
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
pip install alma-memory
|
|
98
|
+
# or from source
|
|
99
|
+
pip install git+https://github.com/RBKunnela/ALMA-memory.git
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Using the Harness Pattern
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
from alma import ALMA, create_harness, Context
|
|
106
|
+
|
|
107
|
+
# Initialize ALMA
|
|
108
|
+
alma = ALMA.from_config(".alma/config.yaml")
|
|
109
|
+
|
|
110
|
+
# Create a domain-specific harness
|
|
111
|
+
harness = create_harness("coding", "helena", alma)
|
|
112
|
+
|
|
113
|
+
# Define task context
|
|
114
|
+
context = Context(
|
|
115
|
+
task="Test the login form validation",
|
|
116
|
+
project_id="my-app",
|
|
117
|
+
user_id="developer-1",
|
|
118
|
+
inputs={"component": "LoginForm", "priority": "high"}
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
# Run with memory injection
|
|
122
|
+
result = harness.run(context)
|
|
123
|
+
|
|
124
|
+
# The harness automatically:
|
|
125
|
+
# 1. Retrieved relevant memories (testing strategies, past outcomes)
|
|
126
|
+
# 2. Built the prompt with injected knowledge
|
|
127
|
+
# 3. Will log the outcome for future learning
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Creating Custom Agents
|
|
131
|
+
|
|
132
|
+
```python
|
|
133
|
+
from alma import (
|
|
134
|
+
ALMA, Harness, Setting, Agent, MemorySchema, Tool, ToolType
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
# Define the environment
|
|
138
|
+
setting = Setting(
|
|
139
|
+
name="Bio Research Environment",
|
|
140
|
+
description="Tools for biological data analysis",
|
|
141
|
+
tools=[
|
|
142
|
+
Tool(
|
|
143
|
+
name="sequence_search",
|
|
144
|
+
description="Search genomic databases",
|
|
145
|
+
tool_type=ToolType.SEARCH,
|
|
146
|
+
),
|
|
147
|
+
Tool(
|
|
148
|
+
name="structure_analysis",
|
|
149
|
+
description="Analyze protein structures",
|
|
150
|
+
tool_type=ToolType.ANALYSIS,
|
|
151
|
+
),
|
|
152
|
+
],
|
|
153
|
+
global_constraints=[
|
|
154
|
+
"Cite all data sources",
|
|
155
|
+
"Note confidence levels",
|
|
156
|
+
],
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
# Define what this agent can learn
|
|
160
|
+
schema = MemorySchema(
|
|
161
|
+
domain="bioinformatics",
|
|
162
|
+
description="Patterns for biological data analysis",
|
|
163
|
+
learnable_categories=[
|
|
164
|
+
"search_refinements",
|
|
165
|
+
"analysis_patterns",
|
|
166
|
+
"data_interpretation",
|
|
167
|
+
],
|
|
168
|
+
forbidden_categories=[
|
|
169
|
+
"medical_diagnosis", # Out of scope
|
|
170
|
+
],
|
|
171
|
+
min_occurrences=5,
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
# Create the agent
|
|
175
|
+
agent = Agent(
|
|
176
|
+
name="bio_researcher",
|
|
177
|
+
role="Bioinformatics Analyst",
|
|
178
|
+
description="Expert in genomic analysis and protein structure prediction",
|
|
179
|
+
memory_schema=schema,
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
# Assemble the harness
|
|
183
|
+
alma = ALMA.from_config(".alma/config.yaml")
|
|
184
|
+
harness = Harness(setting=setting, agent=agent, alma=alma)
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Basic Memory Operations
|
|
188
|
+
|
|
189
|
+
```python
|
|
190
|
+
from alma import ALMA
|
|
191
|
+
|
|
192
|
+
alma = ALMA.from_config(".alma/config.yaml")
|
|
193
|
+
|
|
194
|
+
# Retrieve relevant memories
|
|
195
|
+
memories = alma.retrieve(
|
|
196
|
+
task="Test the login form validation",
|
|
197
|
+
agent="helena",
|
|
198
|
+
top_k=5
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
# Inject into prompt
|
|
202
|
+
prompt = f"""
|
|
203
|
+
## Your Task
|
|
204
|
+
Test the login form validation
|
|
205
|
+
|
|
206
|
+
## Relevant Knowledge (from past runs)
|
|
207
|
+
{memories.to_prompt()}
|
|
208
|
+
"""
|
|
209
|
+
|
|
210
|
+
# After task completion, learn from the outcome
|
|
211
|
+
alma.learn(
|
|
212
|
+
agent="helena",
|
|
213
|
+
task="Test login form",
|
|
214
|
+
outcome="success",
|
|
215
|
+
strategy_used="Tested empty fields, invalid email, valid submission",
|
|
216
|
+
feedback="User confirmed tests were thorough"
|
|
217
|
+
)
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Memory Types
|
|
221
|
+
|
|
222
|
+
| Type | What It Stores | Example |
|
|
223
|
+
|------|----------------|---------|
|
|
224
|
+
| **Heuristic** | Learned strategies | "For forms with >5 fields, test validation incrementally" |
|
|
225
|
+
| **Outcome** | Task results | "Login test succeeded using JWT token strategy" |
|
|
226
|
+
| **Preference** | User constraints | "User prefers verbose test output" |
|
|
227
|
+
| **Domain Knowledge** | Accumulated facts | "Login uses OAuth 2.0 with 24h token expiry" |
|
|
228
|
+
| **Anti-pattern** | What NOT to do | "Don't use sleep() for async waits - causes flaky tests" |
|
|
229
|
+
|
|
230
|
+
## Configuration
|
|
231
|
+
|
|
232
|
+
Create `.alma/config.yaml`:
|
|
233
|
+
|
|
234
|
+
```yaml
|
|
235
|
+
alma:
|
|
236
|
+
project_id: "my-project"
|
|
237
|
+
storage: sqlite # or "azure" for production
|
|
238
|
+
|
|
239
|
+
domains:
|
|
240
|
+
coding:
|
|
241
|
+
enabled: true
|
|
242
|
+
agents: [helena, victor]
|
|
243
|
+
research:
|
|
244
|
+
enabled: true
|
|
245
|
+
agents: [researcher]
|
|
246
|
+
|
|
247
|
+
agents:
|
|
248
|
+
helena:
|
|
249
|
+
domain: coding
|
|
250
|
+
can_learn:
|
|
251
|
+
- testing_strategies
|
|
252
|
+
- selector_patterns
|
|
253
|
+
cannot_learn:
|
|
254
|
+
- backend_logic
|
|
255
|
+
min_occurrences_for_heuristic: 3
|
|
256
|
+
|
|
257
|
+
researcher:
|
|
258
|
+
domain: research
|
|
259
|
+
can_learn:
|
|
260
|
+
- trend_patterns
|
|
261
|
+
- source_reliability
|
|
262
|
+
cannot_learn:
|
|
263
|
+
- code_implementation
|
|
264
|
+
min_occurrences_for_heuristic: 5
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
## Storage Backends
|
|
268
|
+
|
|
269
|
+
| Backend | Use Case | Vector Search |
|
|
270
|
+
|---------|----------|---------------|
|
|
271
|
+
| `azure` | Production | Cosmos DB with vector search |
|
|
272
|
+
| `sqlite` | Local dev | SQLite + FAISS |
|
|
273
|
+
| `file` | Testing | JSON files (no vector search) |
|
|
274
|
+
|
|
275
|
+
## Architecture
|
|
276
|
+
|
|
277
|
+
```
|
|
278
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
279
|
+
│ HARNESS PATTERN │
|
|
280
|
+
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │
|
|
281
|
+
│ │ Setting │ │ Context │ │ Agent │ │MemorySchema │ │
|
|
282
|
+
│ │ (tools) │ │ (task) │ │(executor)│ │ (learning) │ │
|
|
283
|
+
│ └──────────┘ └──────────┘ └──────────┘ └──────────────┘ │
|
|
284
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
285
|
+
↓
|
|
286
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
287
|
+
│ ALMA CORE │
|
|
288
|
+
│ ┌────────────┐ ┌────────────┐ ┌────────────────────────┐ │
|
|
289
|
+
│ │ Retrieval │ │ Learning │ │ Storage │ │
|
|
290
|
+
│ │ Engine │ │ Protocol │ │ (Azure/SQLite/File) │ │
|
|
291
|
+
│ └────────────┘ └────────────┘ └────────────────────────┘ │
|
|
292
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
293
|
+
↓
|
|
294
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
295
|
+
│ MEMORY TYPES │
|
|
296
|
+
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌──────────┐ │
|
|
297
|
+
│ │ Heuristics │ │ Outcomes │ │Preferences │ │Anti-patt.│ │
|
|
298
|
+
│ └────────────┘ └────────────┘ └────────────┘ └──────────┘ │
|
|
299
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
## Documentation
|
|
303
|
+
|
|
304
|
+
- [PRD](docs/architecture/PRD.md) - Full product requirements
|
|
305
|
+
- [Harness Pattern](docs/guides/harness-pattern.md) - Deep dive on the pattern
|
|
306
|
+
- [API Reference](docs/api/) - Coming soon
|
|
307
|
+
|
|
308
|
+
## Status
|
|
309
|
+
|
|
310
|
+
| Phase | Description | Status |
|
|
311
|
+
|-------|-------------|--------|
|
|
312
|
+
| 1 | Core Abstractions | Done |
|
|
313
|
+
| 2 | Local Storage (SQLite + FAISS) | Done |
|
|
314
|
+
| 3 | Retrieval Engine | In Progress |
|
|
315
|
+
| 4 | Learning Protocols | Todo |
|
|
316
|
+
| 5 | Agent Integration (Helena + Victor) | Todo |
|
|
317
|
+
| 6 | Azure Cosmos DB | Todo |
|
|
318
|
+
| 7 | Cache Layer | Todo |
|
|
319
|
+
| 8 | Forgetting Mechanism | Todo |
|
|
320
|
+
|
|
321
|
+
## License
|
|
322
|
+
|
|
323
|
+
MIT
|
|
324
|
+
|
|
325
|
+
## Contributing
|
|
326
|
+
|
|
327
|
+
Contributions welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
alma/__init__.py,sha256=QGUJuT7StZvjzNAwInBgXasEEuoEOMmwMQ9fRtTImQk,1504
|
|
2
|
+
alma/core.py,sha256=-lAYOdnNYDz0ziVQFybLNF_2cDbM8-lIw5xvLuiXZKY,9638
|
|
3
|
+
alma/types.py,sha256=hdBP1dwvYquS7Zej4xb6DM4Bfyx6C2OIFi3vFYo9DMk,6769
|
|
4
|
+
alma/config/__init__.py,sha256=MQ7zjiIFlUnjeI_Nxn4ig0HAmYeUuS7_FVNjYi8Ik3A,99
|
|
5
|
+
alma/config/loader.py,sha256=OJPXTSKrBunl6LMvyb-avSOyH1Pr0IpUZIK9UOmB-LE,4884
|
|
6
|
+
alma/harness/__init__.py,sha256=T25gbnat63HA6QeHY5BiaYxM3BODgQmkcR85DIVjsMc,684
|
|
7
|
+
alma/harness/base.py,sha256=rvgLHVVKo0INDDQTzqYIzEpoNkSiJ0DG5qE_-K4Cc5A,11223
|
|
8
|
+
alma/harness/domains.py,sha256=ur6BqClFd7JgH62DQsC5RBJV-IpEbL9uaEHZzZRtyxI,25720
|
|
9
|
+
alma/integration/__init__.py,sha256=bQZKgA4zhUD3AK4lxh4I7PGukUogKFodIDn3Jurlcws,1276
|
|
10
|
+
alma/integration/claude_agents.py,sha256=HdAZVVIOr7W-_oAuDL4J7ZanvvpOjCP_Lfw-N1TMekI,13318
|
|
11
|
+
alma/integration/helena.py,sha256=rDCYy8Y7_f3xeCzahahio_0OIUury-dMhU7Z_EjWc5w,11885
|
|
12
|
+
alma/integration/victor.py,sha256=Z3FBso38eYs4X6He2qvl_O3Lu9_o5X1dWHvf3PnI0kw,13073
|
|
13
|
+
alma/learning/__init__.py,sha256=GU33u8KUyDgnUASXfAXZ5rMF3sjkdWMzqR5aWAwjWPU,1870
|
|
14
|
+
alma/learning/forgetting.py,sha256=_7BVezNjoEk2AGVARVPr255af3O51vtKR6LW8dMrSwU,45513
|
|
15
|
+
alma/learning/heuristic_extractor.py,sha256=lKM2hGihFjeTolOl58GImfPkaSQOsEqCCjuYPhskJf0,11881
|
|
16
|
+
alma/learning/protocols.py,sha256=yr5JpHQB5ktYtkmSaas6AUp0iWPyoN7ZU39nEdRwUko,10328
|
|
17
|
+
alma/learning/validation.py,sha256=cv4mMTr3hRlC3AxWHG7-w-k_b-dNkowRh-idC18hN6Y,11028
|
|
18
|
+
alma/mcp/__init__.py,sha256=USCtSVAKaW1eFKgdqm50krlufPeccfGw5yDZ4BC2KwE,947
|
|
19
|
+
alma/mcp/__main__.py,sha256=OKNXBY3GBJJKhAjIpGeKYcK02dX_83eOwUXkUXpV54A,3946
|
|
20
|
+
alma/mcp/resources.py,sha256=tdJoBA55qRcdwXCPyaFJ2hR23oQRqfiNUTzHo-h5qfs,3460
|
|
21
|
+
alma/mcp/server.py,sha256=4LPs2J53I4fTXVB5P-1mZibce-FVWrPhFWCoUKHy9TM,19043
|
|
22
|
+
alma/mcp/tools.py,sha256=UEB9NzcjxcpuAiie6sJ_gGdjfP6Ey0ajgp8hZRx3NHE,9452
|
|
23
|
+
alma/retrieval/__init__.py,sha256=lhfJh7Lfi4d0UYzhgVxKPVCO3959eJwCH0VzK4mgTio,1006
|
|
24
|
+
alma/retrieval/cache.py,sha256=mJ-hJUaoX1aUlcQjYsrrYQBKb8F3qIJJe46bSQ2RMg4,34645
|
|
25
|
+
alma/retrieval/embeddings.py,sha256=S7KvogxBNoDP2r5ANwuH0hFdzqsAGXzAqAA8BY0_zMI,6464
|
|
26
|
+
alma/retrieval/engine.py,sha256=RHkCaBbhYMHA44t8CU1W7dxMuUj1yvZ7p_v52cC23bY,9659
|
|
27
|
+
alma/retrieval/scoring.py,sha256=VG41Vq1mV0DgLv0cM7m89KLwRNqOWaLboSRNhoC0cy8,10102
|
|
28
|
+
alma/storage/__init__.py,sha256=PtKICN39q2MQ7CuUmFnERQMIfo8Tbpv_Ro61jLLvUvQ,528
|
|
29
|
+
alma/storage/azure_cosmos.py,sha256=GAeheRabaWXKsXLS66qtl8ALzVk2QM6bw3sgC6ImpSI,32805
|
|
30
|
+
alma/storage/base.py,sha256=-1Xi3zQFdFgdkIWvqLhNNq9SPdjaIYoagijPMKA3I8M,8960
|
|
31
|
+
alma/storage/file_based.py,sha256=g-1dkmu68T6ePhyvh40o_u-THqK1WbXtt4xfccChySM,20709
|
|
32
|
+
alma/storage/sqlite_local.py,sha256=qovQ_vhq67zsrhZLxMtFaCR-9ZPpuV1EAknxmRouqEA,32820
|
|
33
|
+
alma_memory-0.2.0.dist-info/METADATA,sha256=jQQOgv5q1ODVlLdM6lUfdapw4MBAv1HJCmrBR332W0c,12555
|
|
34
|
+
alma_memory-0.2.0.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
|
|
35
|
+
alma_memory-0.2.0.dist-info/top_level.txt,sha256=5oN68LXctTl8a8i1LA-5WqSaP-pDA-J0x1AfCFfLm4A,5
|
|
36
|
+
alma_memory-0.2.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
alma
|