loudiman commited on
Commit
43f1dd5
·
verified ·
1 Parent(s): 409b73e

Add smartFilter module

Browse files
Files changed (1) hide show
  1. src/smartFilter.ts +48 -0
src/smartFilter.ts ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { MemoryConfig, DEFAULT_MEMORY_CONFIG } from './types';
2
+
3
+ type MessageIntent = 'declarative' | 'interrogative' | 'imperative' | 'exclamatory' | 'social';
4
+
5
+ export function classifyMessageIntent(text: string): MessageIntent {
6
+ const t = text.trim();
7
+ if (t.endsWith('?')) return 'interrogative';
8
+ if (/^(what|who|where|when|why|how|which|can|could|would|should|is|are|do|does|did|will|have|has)\s/i.test(t)) return 'interrogative';
9
+ if (/^(tell|show|give|find|get|make|let|help|explain|describe|list|suggest|recommend)\s/i.test(t)) return 'imperative';
10
+ if (/^(hi|hey|hello|bye|goodbye|thanks|thank\s+you|please|sorry|wow|oh|hmm|haha|lol|nice|cool|great|awesome)\b/i.test(t)) return 'social';
11
+ if (t.endsWith('!') && /\b(love|hate|amazing|terrible|awful|great|best|worst)\b/i.test(t)) return 'exclamatory';
12
+ return 'declarative';
13
+ }
14
+
15
+ export function scoreMessageForMemory(text: string, config: MemoryConfig = DEFAULT_MEMORY_CONFIG): { score: number; shouldStore: boolean; reason: string } {
16
+ let score = 0; const reasons: string[] = []; const t = text.trim();
17
+ if (t.length < config.minMessageLength) return { score: 0, shouldStore: false, reason: 'too_short' };
18
+ if (config.skipPatterns.some(p => p.test(t))) return { score: 0, shouldStore: false, reason: 'skip_pattern' };
19
+ const intent = classifyMessageIntent(t);
20
+ switch (intent) {
21
+ case 'declarative': score += 0.4; reasons.push('declarative'); break;
22
+ case 'exclamatory': score += 0.3; reasons.push('exclamatory'); break;
23
+ case 'interrogative': score += 0.05; reasons.push('question'); break;
24
+ case 'imperative': if (/\b(always|never|remember|don't\s+forget)\b/i.test(t)) { score += 0.45; reasons.push('procedural'); } else { score += 0.05; reasons.push('command'); } break;
25
+ case 'social': reasons.push('social'); break;
26
+ }
27
+ if (/\b(i\s+am|i'm|i\s+have|i've|i\s+live|i\s+work|my\s+\w+\s+is)\b/i.test(t)) { score += 0.25; reasons.push('personal_fact'); }
28
+ if (/\b(i\s+(like|love|enjoy|prefer|hate|dislike|always|never))\b/i.test(t)) { score += 0.2; reasons.push('preference'); }
29
+ if (/\b(allergic|can't\s+eat|don't\s+eat|vegetarian|vegan|intolerant|avoid)\b/i.test(t)) { score += 0.3; reasons.push('constraint'); }
30
+ if (/\b(always|never|remember\s+to|remind\s+me|don't\s+forget)\b/i.test(t)) { score += 0.2; reasons.push('procedural_keywords'); }
31
+ if (t.length > 40) score += 0.05;
32
+ if (t.length > 80) score += 0.05;
33
+ score = Math.min(score, 1.0);
34
+ return { score, shouldStore: score >= 0.5, reason: reasons.join(', ') };
35
+ }
36
+
37
+ export function shouldStoreUserMessage(text: string, config: MemoryConfig = DEFAULT_MEMORY_CONFIG): { store: boolean; textToStore: string; reason: string } {
38
+ const segments = text.split(/[.!?]+/).map(s => s.trim()).filter(s => s.length > 5);
39
+ if (segments.length <= 1) {
40
+ const result = scoreMessageForMemory(text, config);
41
+ if (result.reason.includes('constraint') || result.reason.includes('preference'))
42
+ return { store: true, textToStore: text, reason: result.reason };
43
+ return { store: result.shouldStore, textToStore: text, reason: result.reason };
44
+ }
45
+ const storeable = segments.filter(s => scoreMessageForMemory(s, config).shouldStore);
46
+ if (!storeable.length) return { store: false, textToStore: '', reason: 'no_storable_content' };
47
+ return { store: true, textToStore: storeable.join('. ') + '.', reason: 'compound' };
48
+ }