neural-memory 0.1.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.
Files changed (55) hide show
  1. neural_memory/__init__.py +38 -0
  2. neural_memory/cli/__init__.py +15 -0
  3. neural_memory/cli/__main__.py +6 -0
  4. neural_memory/cli/config.py +176 -0
  5. neural_memory/cli/main.py +2702 -0
  6. neural_memory/cli/storage.py +169 -0
  7. neural_memory/cli/tui.py +471 -0
  8. neural_memory/core/__init__.py +52 -0
  9. neural_memory/core/brain.py +301 -0
  10. neural_memory/core/brain_mode.py +273 -0
  11. neural_memory/core/fiber.py +236 -0
  12. neural_memory/core/memory_types.py +331 -0
  13. neural_memory/core/neuron.py +168 -0
  14. neural_memory/core/project.py +257 -0
  15. neural_memory/core/synapse.py +215 -0
  16. neural_memory/engine/__init__.py +15 -0
  17. neural_memory/engine/activation.py +335 -0
  18. neural_memory/engine/encoder.py +391 -0
  19. neural_memory/engine/retrieval.py +440 -0
  20. neural_memory/extraction/__init__.py +42 -0
  21. neural_memory/extraction/entities.py +547 -0
  22. neural_memory/extraction/parser.py +337 -0
  23. neural_memory/extraction/router.py +396 -0
  24. neural_memory/extraction/temporal.py +428 -0
  25. neural_memory/mcp/__init__.py +9 -0
  26. neural_memory/mcp/__main__.py +6 -0
  27. neural_memory/mcp/server.py +621 -0
  28. neural_memory/py.typed +0 -0
  29. neural_memory/safety/__init__.py +31 -0
  30. neural_memory/safety/freshness.py +238 -0
  31. neural_memory/safety/sensitive.py +304 -0
  32. neural_memory/server/__init__.py +5 -0
  33. neural_memory/server/app.py +99 -0
  34. neural_memory/server/dependencies.py +33 -0
  35. neural_memory/server/models.py +138 -0
  36. neural_memory/server/routes/__init__.py +7 -0
  37. neural_memory/server/routes/brain.py +221 -0
  38. neural_memory/server/routes/memory.py +169 -0
  39. neural_memory/server/routes/sync.py +387 -0
  40. neural_memory/storage/__init__.py +17 -0
  41. neural_memory/storage/base.py +441 -0
  42. neural_memory/storage/factory.py +329 -0
  43. neural_memory/storage/memory_store.py +896 -0
  44. neural_memory/storage/shared_store.py +650 -0
  45. neural_memory/storage/sqlite_store.py +1613 -0
  46. neural_memory/sync/__init__.py +5 -0
  47. neural_memory/sync/client.py +435 -0
  48. neural_memory/unified_config.py +315 -0
  49. neural_memory/utils/__init__.py +5 -0
  50. neural_memory/utils/config.py +98 -0
  51. neural_memory-0.1.0.dist-info/METADATA +314 -0
  52. neural_memory-0.1.0.dist-info/RECORD +55 -0
  53. neural_memory-0.1.0.dist-info/WHEEL +4 -0
  54. neural_memory-0.1.0.dist-info/entry_points.txt +4 -0
  55. neural_memory-0.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,337 @@
1
+ """Query parser for decomposing queries into activation signals."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from datetime import datetime
7
+ from enum import StrEnum
8
+
9
+ from neural_memory.extraction.entities import Entity, EntityExtractor, extract_keywords
10
+ from neural_memory.extraction.temporal import TemporalExtractor, TimeHint
11
+
12
+
13
+ class QueryIntent(StrEnum):
14
+ """The intent/purpose of a query."""
15
+
16
+ ASK_WHAT = "ask_what" # What happened?
17
+ ASK_WHERE = "ask_where" # Where did it happen?
18
+ ASK_WHEN = "ask_when" # When did it happen?
19
+ ASK_WHO = "ask_who" # Who was involved?
20
+ ASK_WHY = "ask_why" # Why did it happen?
21
+ ASK_HOW = "ask_how" # How did it happen?
22
+ ASK_FEELING = "ask_feeling" # How did I feel?
23
+ ASK_PATTERN = "ask_pattern" # What's the pattern?
24
+ CONFIRM = "confirm" # Did X happen?
25
+ COMPARE = "compare" # Compare X and Y
26
+ RECALL = "recall" # General recall
27
+ UNKNOWN = "unknown"
28
+
29
+
30
+ class Perspective(StrEnum):
31
+ """The perspective/framing of the query."""
32
+
33
+ RECALL = "recall" # Remember something
34
+ CONFIRM = "confirm" # Verify something
35
+ COMPARE = "compare" # Compare things
36
+ ANALYZE = "analyze" # Analyze/understand
37
+ SUMMARIZE = "summarize" # Get summary
38
+
39
+
40
+ @dataclass
41
+ class Stimulus:
42
+ """
43
+ Decomposed query signals for activation.
44
+
45
+ A Stimulus represents all the extracted signals from a query
46
+ that will be used to activate relevant neurons.
47
+
48
+ Attributes:
49
+ time_hints: Extracted time references
50
+ keywords: Important keywords from the query
51
+ entities: Named entities found
52
+ intent: What the query is asking for
53
+ perspective: How the query frames the request
54
+ raw_query: The original query text
55
+ language: Detected or specified language
56
+ """
57
+
58
+ time_hints: list[TimeHint]
59
+ keywords: list[str]
60
+ entities: list[Entity]
61
+ intent: QueryIntent
62
+ perspective: Perspective
63
+ raw_query: str
64
+ language: str = "auto"
65
+
66
+ @property
67
+ def has_time_context(self) -> bool:
68
+ """Check if query has temporal constraints."""
69
+ return len(self.time_hints) > 0
70
+
71
+ @property
72
+ def has_entities(self) -> bool:
73
+ """Check if query mentions specific entities."""
74
+ return len(self.entities) > 0
75
+
76
+ @property
77
+ def anchor_count(self) -> int:
78
+ """Count of potential anchor points for activation."""
79
+ return len(self.time_hints) + len(self.entities) + len(self.keywords)
80
+
81
+
82
+ class QueryParser:
83
+ """
84
+ Parser for decomposing queries into activation signals.
85
+
86
+ The parser extracts:
87
+ - Temporal references (time hints)
88
+ - Named entities (people, places, etc.)
89
+ - Keywords (important words)
90
+ - Intent (what the query is asking)
91
+ - Perspective (how the query frames the request)
92
+ """
93
+
94
+ # Intent detection patterns
95
+ INTENT_PATTERNS: dict[QueryIntent, list[str]] = {
96
+ QueryIntent.ASK_WHAT: [
97
+ # English
98
+ r"what",
99
+ r"which",
100
+ r"tell me about",
101
+ # Vietnamese
102
+ r"gì",
103
+ r"cái gì",
104
+ r"điều gì",
105
+ r"chuyện gì",
106
+ r"việc gì",
107
+ ],
108
+ QueryIntent.ASK_WHERE: [
109
+ # English
110
+ r"where",
111
+ r"location",
112
+ r"place",
113
+ # Vietnamese
114
+ r"ở đâu",
115
+ r"đâu",
116
+ r"chỗ nào",
117
+ r"nơi nào",
118
+ ],
119
+ QueryIntent.ASK_WHEN: [
120
+ # English
121
+ r"when",
122
+ r"what time",
123
+ # Vietnamese
124
+ r"khi nào",
125
+ r"lúc nào",
126
+ r"bao giờ",
127
+ r"mấy giờ",
128
+ ],
129
+ QueryIntent.ASK_WHO: [
130
+ # English
131
+ r"who",
132
+ r"whom",
133
+ # Vietnamese
134
+ r"ai",
135
+ r"người nào",
136
+ r"với ai",
137
+ ],
138
+ QueryIntent.ASK_WHY: [
139
+ # English
140
+ r"why",
141
+ r"reason",
142
+ r"cause",
143
+ # Vietnamese
144
+ r"tại sao",
145
+ r"vì sao",
146
+ r"lý do",
147
+ ],
148
+ QueryIntent.ASK_HOW: [
149
+ # English
150
+ r"how did",
151
+ r"how was",
152
+ r"how to",
153
+ # Vietnamese
154
+ r"như thế nào",
155
+ r"làm sao",
156
+ r"thế nào",
157
+ r"ra sao",
158
+ ],
159
+ QueryIntent.ASK_FEELING: [
160
+ # English
161
+ r"how (?:did|do) (?:i|you) feel",
162
+ r"feeling",
163
+ r"emotion",
164
+ # Vietnamese
165
+ r"cảm thấy",
166
+ r"cảm xúc",
167
+ r"tâm trạng",
168
+ r"vui không",
169
+ r"buồn không",
170
+ ],
171
+ QueryIntent.ASK_PATTERN: [
172
+ # English
173
+ r"usually",
174
+ r"typically",
175
+ r"pattern",
176
+ r"often",
177
+ r"always",
178
+ # Vietnamese
179
+ r"thường",
180
+ r"hay",
181
+ r"luôn",
182
+ r"mỗi khi",
183
+ ],
184
+ QueryIntent.CONFIRM: [
185
+ # English
186
+ r"did (?:i|we|you)",
187
+ r"was there",
188
+ r"have (?:i|we|you)",
189
+ r"is it true",
190
+ # Vietnamese
191
+ r"có phải",
192
+ r"đúng không",
193
+ r"phải không",
194
+ ],
195
+ QueryIntent.COMPARE: [
196
+ # English
197
+ r"compare",
198
+ r"difference",
199
+ r"versus",
200
+ r"vs",
201
+ r"better",
202
+ r"worse",
203
+ # Vietnamese
204
+ r"so sánh",
205
+ r"khác nhau",
206
+ r"giống nhau",
207
+ r"hơn",
208
+ ],
209
+ }
210
+
211
+ def __init__(
212
+ self,
213
+ temporal_extractor: TemporalExtractor | None = None,
214
+ entity_extractor: EntityExtractor | None = None,
215
+ ) -> None:
216
+ """
217
+ Initialize the parser.
218
+
219
+ Args:
220
+ temporal_extractor: Custom temporal extractor (creates default if None)
221
+ entity_extractor: Custom entity extractor (creates default if None)
222
+ """
223
+ self._temporal = temporal_extractor or TemporalExtractor()
224
+ self._entity = entity_extractor or EntityExtractor()
225
+
226
+ # Compile intent patterns
227
+ import re
228
+
229
+ self._intent_compiled: dict[QueryIntent, list[re.Pattern[str]]] = {}
230
+ for intent, patterns in self.INTENT_PATTERNS.items():
231
+ self._intent_compiled[intent] = [re.compile(p, re.IGNORECASE) for p in patterns]
232
+
233
+ def parse(
234
+ self,
235
+ query: str,
236
+ reference_time: datetime | None = None,
237
+ language: str = "auto",
238
+ ) -> Stimulus:
239
+ """
240
+ Parse a query into a Stimulus.
241
+
242
+ Args:
243
+ query: The query text
244
+ reference_time: Reference time for temporal parsing
245
+ language: "vi", "en", or "auto"
246
+
247
+ Returns:
248
+ Stimulus containing all extracted signals
249
+ """
250
+ if reference_time is None:
251
+ reference_time = datetime.now()
252
+
253
+ # Detect language if auto
254
+ if language == "auto":
255
+ language = self._detect_language(query)
256
+
257
+ # Extract components
258
+ time_hints = self._temporal.extract(query, reference_time, language)
259
+ entities = self._entity.extract(query, language)
260
+ keywords = extract_keywords(query)
261
+
262
+ # Detect intent
263
+ intent = self._detect_intent(query)
264
+
265
+ # Detect perspective
266
+ perspective = self._detect_perspective(query, intent)
267
+
268
+ return Stimulus(
269
+ time_hints=time_hints,
270
+ keywords=keywords,
271
+ entities=entities,
272
+ intent=intent,
273
+ perspective=perspective,
274
+ raw_query=query,
275
+ language=language,
276
+ )
277
+
278
+ def _detect_language(self, text: str) -> str:
279
+ """Simple language detection."""
280
+ # Vietnamese-specific characters
281
+ vi_chars = set("àáảãạăằắẳẵặâầấẩẫậèéẻẽẹêềếểễệìíỉĩịòóỏõọôồốổỗộơờớởỡợùúủũụưừứửữựỳýỷỹỵđ")
282
+
283
+ text_lower = text.lower()
284
+ vi_count = sum(1 for c in text_lower if c in vi_chars)
285
+
286
+ # If significant Vietnamese characters, it's Vietnamese
287
+ if vi_count > len(text) * 0.05:
288
+ return "vi"
289
+
290
+ # Check for Vietnamese words
291
+ vi_words = {"của", "và", "là", "có", "được", "cho", "với", "này", "trong", "để", "các"}
292
+ words = set(text_lower.split())
293
+ if words & vi_words:
294
+ return "vi"
295
+
296
+ return "en"
297
+
298
+ def _detect_intent(self, query: str) -> QueryIntent:
299
+ """Detect the query intent."""
300
+ query_lower = query.lower()
301
+
302
+ for intent, patterns in self._intent_compiled.items():
303
+ for pattern in patterns:
304
+ if pattern.search(query_lower):
305
+ return intent
306
+
307
+ return QueryIntent.RECALL
308
+
309
+ def _detect_perspective(
310
+ self,
311
+ query: str,
312
+ intent: QueryIntent,
313
+ ) -> Perspective:
314
+ """Detect the query perspective."""
315
+ query_lower = query.lower()
316
+
317
+ # Check for confirmation patterns
318
+ if intent == QueryIntent.CONFIRM:
319
+ return Perspective.CONFIRM
320
+
321
+ # Check for comparison patterns
322
+ if intent == QueryIntent.COMPARE:
323
+ return Perspective.COMPARE
324
+
325
+ # Check for summary patterns
326
+ summary_patterns = ["summary", "summarize", "tóm tắt", "overview", "tổng kết"]
327
+ for pattern in summary_patterns:
328
+ if pattern in query_lower:
329
+ return Perspective.SUMMARIZE
330
+
331
+ # Check for analysis patterns
332
+ analysis_patterns = ["analyze", "understand", "explain", "phân tích", "giải thích"]
333
+ for pattern in analysis_patterns:
334
+ if pattern in query_lower:
335
+ return Perspective.ANALYZE
336
+
337
+ return Perspective.RECALL