alma-memory 0.5.1__py3-none-any.whl → 0.7.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 +296 -226
- alma/compression/__init__.py +33 -0
- alma/compression/pipeline.py +980 -0
- alma/confidence/__init__.py +47 -47
- alma/confidence/engine.py +540 -540
- alma/confidence/types.py +351 -351
- alma/config/loader.py +157 -157
- alma/consolidation/__init__.py +23 -23
- alma/consolidation/engine.py +678 -678
- alma/consolidation/prompts.py +84 -84
- alma/core.py +1189 -430
- alma/domains/__init__.py +30 -30
- alma/domains/factory.py +359 -359
- alma/domains/schemas.py +448 -448
- alma/domains/types.py +272 -272
- alma/events/__init__.py +75 -75
- alma/events/emitter.py +285 -284
- alma/events/storage_mixin.py +246 -246
- alma/events/types.py +126 -126
- alma/events/webhook.py +425 -425
- alma/exceptions.py +49 -49
- alma/extraction/__init__.py +31 -31
- alma/extraction/auto_learner.py +265 -265
- alma/extraction/extractor.py +420 -420
- alma/graph/__init__.py +106 -106
- alma/graph/backends/__init__.py +32 -32
- alma/graph/backends/kuzu.py +624 -624
- alma/graph/backends/memgraph.py +432 -432
- alma/graph/backends/memory.py +236 -236
- alma/graph/backends/neo4j.py +417 -417
- alma/graph/base.py +159 -159
- alma/graph/extraction.py +198 -198
- alma/graph/store.py +860 -860
- alma/harness/__init__.py +35 -35
- alma/harness/base.py +386 -386
- alma/harness/domains.py +705 -705
- alma/initializer/__init__.py +37 -37
- alma/initializer/initializer.py +418 -418
- alma/initializer/types.py +250 -250
- alma/integration/__init__.py +62 -62
- alma/integration/claude_agents.py +444 -444
- alma/integration/helena.py +423 -423
- alma/integration/victor.py +471 -471
- alma/learning/__init__.py +101 -86
- alma/learning/decay.py +878 -0
- alma/learning/forgetting.py +1446 -1446
- alma/learning/heuristic_extractor.py +390 -390
- alma/learning/protocols.py +374 -374
- alma/learning/validation.py +346 -346
- alma/mcp/__init__.py +123 -45
- alma/mcp/__main__.py +156 -156
- alma/mcp/resources.py +122 -122
- alma/mcp/server.py +955 -591
- alma/mcp/tools.py +3254 -509
- alma/observability/__init__.py +91 -84
- alma/observability/config.py +302 -302
- alma/observability/guidelines.py +170 -0
- alma/observability/logging.py +424 -424
- alma/observability/metrics.py +583 -583
- alma/observability/tracing.py +440 -440
- alma/progress/__init__.py +21 -21
- alma/progress/tracker.py +607 -607
- alma/progress/types.py +250 -250
- alma/retrieval/__init__.py +134 -53
- alma/retrieval/budget.py +525 -0
- alma/retrieval/cache.py +1304 -1061
- alma/retrieval/embeddings.py +202 -202
- alma/retrieval/engine.py +850 -427
- alma/retrieval/modes.py +365 -0
- alma/retrieval/progressive.py +560 -0
- alma/retrieval/scoring.py +344 -344
- alma/retrieval/trust_scoring.py +637 -0
- alma/retrieval/verification.py +797 -0
- alma/session/__init__.py +19 -19
- alma/session/manager.py +442 -399
- alma/session/types.py +288 -288
- alma/storage/__init__.py +101 -90
- alma/storage/archive.py +233 -0
- alma/storage/azure_cosmos.py +1259 -1259
- alma/storage/base.py +1083 -583
- alma/storage/chroma.py +1443 -1443
- alma/storage/constants.py +103 -103
- alma/storage/file_based.py +614 -614
- alma/storage/migrations/__init__.py +21 -21
- alma/storage/migrations/base.py +321 -321
- alma/storage/migrations/runner.py +323 -323
- alma/storage/migrations/version_stores.py +337 -337
- alma/storage/migrations/versions/__init__.py +11 -11
- alma/storage/migrations/versions/v1_0_0.py +373 -373
- alma/storage/migrations/versions/v1_1_0_workflow_context.py +551 -0
- alma/storage/pinecone.py +1080 -1080
- alma/storage/postgresql.py +1948 -1559
- alma/storage/qdrant.py +1306 -1306
- alma/storage/sqlite_local.py +3041 -1457
- alma/testing/__init__.py +46 -46
- alma/testing/factories.py +301 -301
- alma/testing/mocks.py +389 -389
- alma/types.py +292 -264
- alma/utils/__init__.py +19 -0
- alma/utils/tokenizer.py +521 -0
- alma/workflow/__init__.py +83 -0
- alma/workflow/artifacts.py +170 -0
- alma/workflow/checkpoint.py +311 -0
- alma/workflow/context.py +228 -0
- alma/workflow/outcomes.py +189 -0
- alma/workflow/reducers.py +393 -0
- {alma_memory-0.5.1.dist-info → alma_memory-0.7.0.dist-info}/METADATA +210 -72
- alma_memory-0.7.0.dist-info/RECORD +112 -0
- alma_memory-0.5.1.dist-info/RECORD +0 -93
- {alma_memory-0.5.1.dist-info → alma_memory-0.7.0.dist-info}/WHEEL +0 -0
- {alma_memory-0.5.1.dist-info → alma_memory-0.7.0.dist-info}/top_level.txt +0 -0
alma/types.py
CHANGED
|
@@ -1,264 +1,292 @@
|
|
|
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, timezone
|
|
9
|
-
from enum import Enum
|
|
10
|
-
from typing import Any, Dict, List, Optional
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
default_factory=list
|
|
40
|
-
) # Agents
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
if
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
""
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
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, timezone
|
|
9
|
+
from enum import Enum
|
|
10
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from alma.workflow.outcomes import WorkflowOutcome
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class MemoryType(Enum):
|
|
17
|
+
"""Categories of memory that agents can store and retrieve."""
|
|
18
|
+
|
|
19
|
+
HEURISTIC = "heuristic"
|
|
20
|
+
OUTCOME = "outcome"
|
|
21
|
+
USER_PREFERENCE = "user_preference"
|
|
22
|
+
DOMAIN_KNOWLEDGE = "domain_knowledge"
|
|
23
|
+
ANTI_PATTERN = "anti_pattern"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass
|
|
27
|
+
class MemoryScope:
|
|
28
|
+
"""
|
|
29
|
+
Defines what an agent is allowed to learn and share.
|
|
30
|
+
|
|
31
|
+
Prevents scope creep by explicitly listing allowed and forbidden domains.
|
|
32
|
+
Supports multi-agent memory sharing through share_with and inherit_from.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
agent_name: str
|
|
36
|
+
can_learn: List[str]
|
|
37
|
+
cannot_learn: List[str]
|
|
38
|
+
share_with: List[str] = field(
|
|
39
|
+
default_factory=list
|
|
40
|
+
) # Agents that can read this agent's memories
|
|
41
|
+
inherit_from: List[str] = field(
|
|
42
|
+
default_factory=list
|
|
43
|
+
) # Agents whose memories this agent can read
|
|
44
|
+
min_occurrences_for_heuristic: int = 3
|
|
45
|
+
|
|
46
|
+
def is_allowed(self, domain: str) -> bool:
|
|
47
|
+
"""Check if learning in this domain is permitted."""
|
|
48
|
+
if domain in self.cannot_learn:
|
|
49
|
+
return False
|
|
50
|
+
if not self.can_learn: # Empty means all allowed (except cannot_learn)
|
|
51
|
+
return True
|
|
52
|
+
return domain in self.can_learn
|
|
53
|
+
|
|
54
|
+
def get_readable_agents(self) -> List[str]:
|
|
55
|
+
"""
|
|
56
|
+
Get list of agents whose memories this agent can read.
|
|
57
|
+
|
|
58
|
+
Returns:
|
|
59
|
+
List containing this agent's name plus all inherited agents.
|
|
60
|
+
"""
|
|
61
|
+
return [self.agent_name] + list(self.inherit_from)
|
|
62
|
+
|
|
63
|
+
def can_read_from(self, other_agent: str) -> bool:
|
|
64
|
+
"""
|
|
65
|
+
Check if this agent can read memories from another agent.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
other_agent: Name of the agent to check
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
True if this agent can read from other_agent
|
|
72
|
+
"""
|
|
73
|
+
return other_agent == self.agent_name or other_agent in self.inherit_from
|
|
74
|
+
|
|
75
|
+
def shares_with(self, other_agent: str) -> bool:
|
|
76
|
+
"""
|
|
77
|
+
Check if this agent shares memories with another agent.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
other_agent: Name of the agent to check
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
True if this agent shares with other_agent
|
|
84
|
+
"""
|
|
85
|
+
return other_agent in self.share_with
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@dataclass
|
|
89
|
+
class Heuristic:
|
|
90
|
+
"""
|
|
91
|
+
A learned rule: "When condition X, strategy Y works N% of the time."
|
|
92
|
+
|
|
93
|
+
Heuristics are only created after min_occurrences validations.
|
|
94
|
+
"""
|
|
95
|
+
|
|
96
|
+
id: str
|
|
97
|
+
agent: str
|
|
98
|
+
project_id: str
|
|
99
|
+
condition: str # "form with multiple required fields"
|
|
100
|
+
strategy: str # "test happy path first, then individual validation"
|
|
101
|
+
confidence: float # 0.0 to 1.0
|
|
102
|
+
occurrence_count: int
|
|
103
|
+
success_count: int
|
|
104
|
+
last_validated: datetime
|
|
105
|
+
created_at: datetime
|
|
106
|
+
embedding: Optional[List[float]] = None
|
|
107
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
108
|
+
|
|
109
|
+
@property
|
|
110
|
+
def success_rate(self) -> float:
|
|
111
|
+
"""Calculate success rate from occurrences."""
|
|
112
|
+
if self.occurrence_count == 0:
|
|
113
|
+
return 0.0
|
|
114
|
+
return self.success_count / self.occurrence_count
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
@dataclass
|
|
118
|
+
class Outcome:
|
|
119
|
+
"""
|
|
120
|
+
Record of a task execution - success or failure with context.
|
|
121
|
+
|
|
122
|
+
Outcomes are raw data that can be consolidated into heuristics.
|
|
123
|
+
"""
|
|
124
|
+
|
|
125
|
+
id: str
|
|
126
|
+
agent: str
|
|
127
|
+
project_id: str
|
|
128
|
+
task_type: str # "api_validation", "form_testing", etc.
|
|
129
|
+
task_description: str
|
|
130
|
+
success: bool
|
|
131
|
+
strategy_used: str
|
|
132
|
+
duration_ms: Optional[int] = None
|
|
133
|
+
error_message: Optional[str] = None
|
|
134
|
+
user_feedback: Optional[str] = None
|
|
135
|
+
timestamp: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
|
|
136
|
+
embedding: Optional[List[float]] = None
|
|
137
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
@dataclass
|
|
141
|
+
class UserPreference:
|
|
142
|
+
"""
|
|
143
|
+
A remembered user constraint or communication preference.
|
|
144
|
+
|
|
145
|
+
Persists across sessions so users don't repeat themselves.
|
|
146
|
+
"""
|
|
147
|
+
|
|
148
|
+
id: str
|
|
149
|
+
user_id: str
|
|
150
|
+
category: str # "communication", "code_style", "workflow"
|
|
151
|
+
preference: str # "No emojis in documentation"
|
|
152
|
+
source: str # "explicit_instruction", "inferred_from_correction"
|
|
153
|
+
confidence: float = 1.0 # Lower for inferred preferences
|
|
154
|
+
timestamp: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
|
|
155
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
@dataclass
|
|
159
|
+
class DomainKnowledge:
|
|
160
|
+
"""
|
|
161
|
+
Accumulated domain-specific facts within agent's scope.
|
|
162
|
+
|
|
163
|
+
Different from heuristics - these are facts, not strategies.
|
|
164
|
+
"""
|
|
165
|
+
|
|
166
|
+
id: str
|
|
167
|
+
agent: str
|
|
168
|
+
project_id: str
|
|
169
|
+
domain: str # "authentication", "database_schema", etc.
|
|
170
|
+
fact: str # "Login endpoint uses JWT with 24h expiry"
|
|
171
|
+
source: str # "code_analysis", "documentation", "user_stated"
|
|
172
|
+
confidence: float = 1.0
|
|
173
|
+
last_verified: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
|
|
174
|
+
embedding: Optional[List[float]] = None
|
|
175
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
@dataclass
|
|
179
|
+
class AntiPattern:
|
|
180
|
+
"""
|
|
181
|
+
What NOT to do - learned from validated failures.
|
|
182
|
+
|
|
183
|
+
Helps agents avoid repeating mistakes.
|
|
184
|
+
"""
|
|
185
|
+
|
|
186
|
+
id: str
|
|
187
|
+
agent: str
|
|
188
|
+
project_id: str
|
|
189
|
+
pattern: str # "Using fixed sleep() for async waits"
|
|
190
|
+
why_bad: str # "Causes flaky tests, doesn't adapt to load"
|
|
191
|
+
better_alternative: str # "Use explicit waits with conditions"
|
|
192
|
+
occurrence_count: int
|
|
193
|
+
last_seen: datetime
|
|
194
|
+
created_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
|
|
195
|
+
embedding: Optional[List[float]] = None
|
|
196
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
@dataclass
|
|
200
|
+
class MemorySlice:
|
|
201
|
+
"""
|
|
202
|
+
A compact, relevant subset of memories for injection into context.
|
|
203
|
+
|
|
204
|
+
This is what gets injected per-call - must stay under token budget.
|
|
205
|
+
"""
|
|
206
|
+
|
|
207
|
+
heuristics: List[Heuristic] = field(default_factory=list)
|
|
208
|
+
outcomes: List[Outcome] = field(default_factory=list)
|
|
209
|
+
preferences: List[UserPreference] = field(default_factory=list)
|
|
210
|
+
domain_knowledge: List[DomainKnowledge] = field(default_factory=list)
|
|
211
|
+
anti_patterns: List[AntiPattern] = field(default_factory=list)
|
|
212
|
+
|
|
213
|
+
# Workflow outcomes (v0.6.0+)
|
|
214
|
+
workflow_outcomes: List["WorkflowOutcome"] = field(default_factory=list)
|
|
215
|
+
|
|
216
|
+
# Retrieval metadata
|
|
217
|
+
query: Optional[str] = None
|
|
218
|
+
agent: Optional[str] = None
|
|
219
|
+
retrieval_time_ms: Optional[int] = None
|
|
220
|
+
|
|
221
|
+
def to_prompt(
|
|
222
|
+
self,
|
|
223
|
+
max_tokens: int = 2000,
|
|
224
|
+
model: Optional[str] = None,
|
|
225
|
+
) -> str:
|
|
226
|
+
"""
|
|
227
|
+
Format memories for injection into agent context.
|
|
228
|
+
|
|
229
|
+
Respects token budget by prioritizing high-confidence items.
|
|
230
|
+
Uses accurate token counting via tiktoken when available.
|
|
231
|
+
|
|
232
|
+
Args:
|
|
233
|
+
max_tokens: Maximum tokens allowed for the output
|
|
234
|
+
model: Optional model name for accurate tokenization
|
|
235
|
+
(e.g., "gpt-4", "claude-3-sonnet"). If not provided,
|
|
236
|
+
uses a general-purpose estimation.
|
|
237
|
+
|
|
238
|
+
Returns:
|
|
239
|
+
Formatted prompt string, truncated if necessary
|
|
240
|
+
"""
|
|
241
|
+
from alma.utils.tokenizer import TokenEstimator
|
|
242
|
+
|
|
243
|
+
# Initialize token estimator
|
|
244
|
+
estimator = TokenEstimator(model=model) if model else TokenEstimator()
|
|
245
|
+
|
|
246
|
+
sections = []
|
|
247
|
+
|
|
248
|
+
if self.heuristics:
|
|
249
|
+
h_text = "## Relevant Strategies\n"
|
|
250
|
+
for h in sorted(self.heuristics, key=lambda x: -x.confidence)[:5]:
|
|
251
|
+
h_text += f"- When: {h.condition}\n Do: {h.strategy} (confidence: {h.confidence:.0%})\n"
|
|
252
|
+
sections.append(h_text)
|
|
253
|
+
|
|
254
|
+
if self.anti_patterns:
|
|
255
|
+
ap_text = "## Avoid These Patterns\n"
|
|
256
|
+
for ap in self.anti_patterns[:3]:
|
|
257
|
+
ap_text += f"- Don't: {ap.pattern}\n Why: {ap.why_bad}\n Instead: {ap.better_alternative}\n"
|
|
258
|
+
sections.append(ap_text)
|
|
259
|
+
|
|
260
|
+
if self.preferences:
|
|
261
|
+
p_text = "## User Preferences\n"
|
|
262
|
+
for p in self.preferences[:5]:
|
|
263
|
+
p_text += f"- {p.preference}\n"
|
|
264
|
+
sections.append(p_text)
|
|
265
|
+
|
|
266
|
+
if self.domain_knowledge:
|
|
267
|
+
dk_text = "## Domain Context\n"
|
|
268
|
+
for dk in self.domain_knowledge[:5]:
|
|
269
|
+
dk_text += f"- {dk.fact}\n"
|
|
270
|
+
sections.append(dk_text)
|
|
271
|
+
|
|
272
|
+
result = "\n".join(sections)
|
|
273
|
+
|
|
274
|
+
# Use accurate token estimation and truncation
|
|
275
|
+
result = estimator.truncate_to_token_limit(
|
|
276
|
+
text=result,
|
|
277
|
+
max_tokens=max_tokens,
|
|
278
|
+
suffix="\n[truncated]",
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
return result
|
|
282
|
+
|
|
283
|
+
@property
|
|
284
|
+
def total_items(self) -> int:
|
|
285
|
+
"""Total number of memory items in this slice."""
|
|
286
|
+
return (
|
|
287
|
+
len(self.heuristics)
|
|
288
|
+
+ len(self.outcomes)
|
|
289
|
+
+ len(self.preferences)
|
|
290
|
+
+ len(self.domain_knowledge)
|
|
291
|
+
+ len(self.anti_patterns)
|
|
292
|
+
)
|
alma/utils/__init__.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ALMA Utility modules.
|
|
3
|
+
|
|
4
|
+
Provides shared utilities for token estimation and other common functionality.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from alma.utils.tokenizer import (
|
|
8
|
+
ModelTokenBudget,
|
|
9
|
+
TokenEstimator,
|
|
10
|
+
get_default_token_budget,
|
|
11
|
+
get_token_estimator,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
"TokenEstimator",
|
|
16
|
+
"ModelTokenBudget",
|
|
17
|
+
"get_token_estimator",
|
|
18
|
+
"get_default_token_budget",
|
|
19
|
+
]
|