33
44This specialized classifier focuses ONLY on memory operations,
55achieving higher accuracy than the general classifier.
6+
7+ Uses tool semantic metadata for action hints when available.
68"""
79
8- from typing import Dict
10+ from typing import Dict , Optional , TYPE_CHECKING
911from .neuron import BaseNeuron
1012
13+ if TYPE_CHECKING :
14+ from neural_engine .core .tool_discovery import ToolDiscovery
15+
1116
1217class MemoryOperationsSpecialist (BaseNeuron ):
1318 """
@@ -16,14 +21,54 @@ class MemoryOperationsSpecialist(BaseNeuron):
1621 Distinguishes between:
1722 - memory_write: Storing information
1823 - memory_read: Retrieving information
24+
25+ Uses semantic metadata from tools when available.
1926 """
2027
21- def __init__ (self , message_bus , ollama_client ):
28+ def __init__ (self , message_bus , ollama_client , tool_discovery : Optional [ 'ToolDiscovery' ] = None ):
2229 super ().__init__ (message_bus , ollama_client )
30+ self .tool_discovery = tool_discovery
31+
32+ # Cache tool action hints (populated from semantic metadata)
33+ self ._write_actions = {"store" , "save" , "write" , "remember" , "memorize" , "note" }
34+ self ._read_actions = {"retrieve" , "recall" , "get" , "read" , "fetch" }
35+
36+ def set_tool_discovery (self , tool_discovery : 'ToolDiscovery' ):
37+ """Set tool discovery and update action hints from metadata."""
38+ self .tool_discovery = tool_discovery
39+ self ._update_action_hints ()
40+
41+ def _update_action_hints (self ):
42+ """Update action hints from tool semantic metadata."""
43+ if not self .tool_discovery :
44+ return
45+
46+ # Get memory tools and extract their action metadata
47+ try :
48+ tools = self .tool_discovery .tool_registry .get_all_tools ()
49+
50+ for tool_name , tool_instance in tools .items ():
51+ if hasattr (tool_instance , 'get_semantic_metadata' ):
52+ metadata = tool_instance .get_semantic_metadata ()
53+ if metadata .get ('domain' ) == 'memory' :
54+ actions = set (metadata .get ('actions' , []))
55+ synonyms = set (metadata .get ('synonyms' , []))
56+
57+ # memory_write actions
58+ if 'store' in actions or 'save' in actions or 'write' in actions :
59+ self ._write_actions .update (actions )
60+ self ._write_actions .update (synonyms )
61+
62+ # memory_read actions
63+ if 'retrieve' in actions or 'read' in actions or 'get' in actions :
64+ self ._read_actions .update (actions )
65+ self ._read_actions .update (synonyms )
66+ except Exception :
67+ pass # Keep defaults if tool discovery fails
2368
2469 def classify_memory_operation (self , goal : str ) -> str :
2570 """
26- Classify memory operation type.
71+ Classify memory operation type using LLM with semantic-aware fallback .
2772
2873 Args:
2974 goal: User goal text
@@ -43,19 +88,6 @@ def classify_memory_operation(self, goal: str) -> str:
4388 "- Questions (What? Tell me? Recall?) → read\n "
4489 "- Commands to store (Remember that X, Save Y) → write\n "
4590 "- Past tense recall (what I told you, what you know) → read\n \n "
46- "Examples:\n "
47- "User: Remember that my name is Alice\n "
48- "Assistant: write\n \n "
49- "User: What is my name?\n "
50- "Assistant: read\n \n "
51- "User: Remember what I told you about my favorite color\n "
52- "Assistant: read\n \n "
53- "User: Store the value 42 for key 'answer'\n "
54- "Assistant: write\n \n "
55- "User: Recall what I told you about my birthday\n "
56- "Assistant: read\n \n "
57- "User: What did I tell you?\n "
58- "Assistant: read\n \n "
5991 "Respond with ONLY 'write' or 'read'."
6092 )
6193 },
@@ -65,44 +97,40 @@ def classify_memory_operation(self, goal: str) -> str:
6597 response = self .ollama_client .chat (messages )
6698 operation = response ['message' ]['content' ].strip ().lower ()
6799
68- # Fallback: analyze keywords FIRST before trusting LLM response
100+ # Semantic-aware fallback using action hints from tool metadata
69101 goal_lower = goal .lower ()
70102
71- # Strongest WRITE signals - statements of fact with "my X is Y" pattern
72- if any (p in goal_lower for p in ["my name is" , "my favorite" , "i am" , "i'm from" , "i like" , "i live" , "actually" ]):
73- # Check if it's a question (would be read)
74- if not any (q in goal_lower for q in ["what" , "who" , "when" , "where" , "why" , "how" , "tell me" , "?" , "recall" ]):
75- return "write"
103+ # Check if goal contains write actions (from semantic metadata)
104+ write_action_score = sum (1 for action in self ._write_actions if action in goal_lower )
105+ read_action_score = sum (1 for action in self ._read_actions if action in goal_lower )
76106
77- # Strongest READ signals - past tense recall patterns
78- if any (p in goal_lower for p in ["what i told" , "what i said" , "what you know" , "told you about" , "said earlier" , "remember what" ]):
79- return "read"
107+ # Linguistic patterns for read/write detection (grammatical, not domain-specific)
108+ # These are OK because they detect SENTENCE STRUCTURE, not topic
109+ is_statement = any (p in goal_lower for p in ["my name is" , "my favorite is" , "i am " , "i like " ])
110+ is_question = "?" in goal or any (q in goal_lower for q in ["what is" , "who is" , "tell me" ])
111+ is_recall = any (p in goal_lower for p in ["what i told" , "what you know" , "do you remember" ])
80112
81- # Question words strongly indicate read
82- if any (q in goal_lower for q in ["what is" , "who is" , "when did" , "where is" , "why did" , "how did" , "tell me" , "show me" , "recall" ]):
113+ # Combine signals
114+ if is_statement and not is_question and not is_recall :
115+ return "write"
116+
117+ if is_question or is_recall :
83118 return "read"
84119
85- # Validate and clean LLM response
86- if "write" in operation or "stor" in operation or "save" in operation :
120+ # Use action scores from semantic metadata
121+ if write_action_score > read_action_score :
87122 return "write"
88- elif "read" in operation or "recall" in operation or "get" in operation :
123+ elif read_action_score > write_action_score :
89124 return "read"
90- else :
91- # Final fallback: check for explicit write commands
92- write_patterns = ["remember that" , "store" , "save" , "write" , "note that" , "set" ]
93- read_patterns = ["recall" , "retrieve" , "get" , "fetch" ]
94-
95- # Check for explicit write patterns with "that" clause
96- for pattern in write_patterns :
97- if pattern in goal_lower and "that" in goal_lower :
98- return "write"
99-
100- # Check for read patterns
101- if any (p in goal_lower for p in read_patterns ):
102- return "read"
103-
104- # Default to read if uncertain (safer - read has no side effects)
125+
126+ # Trust LLM response as final fallback
127+ if "write" in operation or "stor" in operation :
128+ return "write"
129+ elif "read" in operation or "recall" in operation :
105130 return "read"
131+
132+ # Default to read (safer - no side effects)
133+ return "read"
106134
107135 def select_memory_tool (self , goal : str ) -> Dict :
108136 """
0 commit comments