Download src/core/knowledgeGaps.ts from agenthinkmesh/meezan: direct link, hf CLI and curl.
- Browser
- Download file 8.02 kB
-
https://huggingface.co/agenthinkmesh/meezan/resolve/main/src/core/knowledgeGaps.ts
- Command line
-
hf download hf://agenthinkmesh/meezan/src/core/knowledgeGaps.ts
-
curl -L -o knowledgeGaps.ts https://huggingface.co/agenthinkmesh/meezan/resolve/main/src/core/knowledgeGaps.ts
8.02 kB
| // ========================================== | |
| // MEEZAN - ميزان Knowledge Gap Tracker | |
| // Identifies what Meezan doesn't know well | |
| // and prioritizes what to learn next | |
| // ========================================== | |
| import * as fs from 'fs'; | |
| import * as path from 'path'; | |
| import { KnowledgeGap } from '../types'; | |
| // Topic patterns to detect knowledge domains | |
| const TOPIC_PATTERNS: Array<{ | |
| topic: string; | |
| topicAr: string; | |
| category: KnowledgeGap['category']; | |
| patterns: string[]; | |
| }> = [ | |
| // Fiqh topics | |
| { topic: 'Inheritance (Faraidh)', topicAr: 'الميراث والفرائض', category: 'fiqh', | |
| patterns: ['ميراث', 'فرائض', 'وصية', 'inheritance', 'faraidh', 'تركة'] }, | |
| { topic: 'Islamic Marriage (Nikah)', topicAr: 'النكاح والزواج', category: 'fiqh', | |
| patterns: ['نكاح', 'زواج', 'مهر', 'طلاق', 'marriage', 'nikah', 'divorce', 'khul'] }, | |
| { topic: 'Halal Food Details', topicAr: 'تفاصيل الأطعمة الحلال', category: 'fiqh', | |
| patterns: ['ذبح', 'تذكية', 'مستفسر', 'slaughter', 'zabiha', 'gelatin', 'rennet'] }, | |
| { topic: 'Business Ethics in Islam', topicAr: 'أخلاقيات التجارة الإسلامية', category: 'fiqh', | |
| patterns: ['غش', 'تدليس', 'عقد', 'بيع', 'شراء', 'fraud', 'contract', 'gharar'] }, | |
| // Islamic Finance | |
| { topic: 'Sukuk Details', topicAr: 'تفاصيل الصكوك', category: 'finance', | |
| patterns: ['صكوك', 'sukuk', 'islamic bond', 'صك'] }, | |
| { topic: 'Islamic Insurance (Takaful)', topicAr: 'التأمين الإسلامي', category: 'finance', | |
| patterns: ['تكافل', 'تأمين', 'takaful', 'insurance'] }, | |
| { topic: 'Cryptocurrency in Islam', topicAr: 'العملات الرقمية في الإسلام', category: 'finance', | |
| patterns: ['بيتكوين', 'كريبتو', 'عملة رقمية', 'bitcoin', 'crypto', 'nft', 'defi', 'web3'] }, | |
| { topic: 'Kuwait Stock Exchange', topicAr: 'بورصة الكويت', category: 'finance', | |
| patterns: ['بورصة الكويت', 'boursa kuwait', 'كويت للأسهم', 'kuwaitstock', 'tadawul'] }, | |
| // Kuwait Government | |
| { topic: 'Kuwait Visa Process', topicAr: 'إجراءات التأشيرة الكويتية', category: 'government', | |
| patterns: ['تأشيرة', 'visa', 'iqama', 'إقامة', 'residence permit', 'work permit'] }, | |
| { topic: 'Kuwait Labor Law', topicAr: 'قانون العمل الكويتي', category: 'government', | |
| patterns: ['عمالة', 'labor', 'employment', 'عقد عمل', 'راتب', 'فصل', 'resignation'] }, | |
| { topic: 'Kuwait VAT / Tax', topicAr: 'الضرائب الكويتية', category: 'government', | |
| patterns: ['ضريبة', 'vat', 'tax', 'زكاة الشركات', 'corporate tax'] }, | |
| // Culture | |
| { topic: 'Ramadan Practices', topicAr: 'أحكام رمضان', category: 'culture', | |
| patterns: ['رمضان', 'صيام', 'إفطار', 'سحور', 'fasting', 'ramadan', 'iftar', 'suhoor'] }, | |
| { topic: 'Hajj and Umrah', topicAr: 'الحج والعمرة', category: 'culture', | |
| patterns: ['حج', 'عمرة', 'مكة', 'hajj', 'umrah', 'mecca', 'ihram'] }, | |
| { topic: 'GCC Cultural Etiquette', topicAr: 'الآداب الخليجية', category: 'culture', | |
| patterns: ['عادات', 'تقاليد', 'آداب', 'culture', 'etiquette', 'customs', 'خليج'] }, | |
| ]; | |
| export class KnowledgeGapTracker { | |
| private dbPath: string; | |
| private gaps: Map<string, KnowledgeGap>; | |
| constructor(dbPath: string = './data/knowledge_gaps.json') { | |
| this.dbPath = dbPath; | |
| this.gaps = new Map(); | |
| this.load(); | |
| } | |
| /** | |
| * Analyze a conversation exchange and detect potential knowledge gaps | |
| */ | |
| analyzeExchange( | |
| userMessage: string, | |
| assistantResponse: string, | |
| wasConfused: boolean, | |
| wasNegative: boolean | |
| ): KnowledgeGap[] { | |
| const detectedGaps: KnowledgeGap[] = []; | |
| if (!wasConfused && !wasNegative) return detectedGaps; | |
| const combined = (userMessage + ' ' + assistantResponse).toLowerCase(); | |
| for (const topicDef of TOPIC_PATTERNS) { | |
| const matches = topicDef.patterns.filter(p => combined.includes(p.toLowerCase())); | |
| if (matches.length > 0) { | |
| const gapId = `gap_${topicDef.topic.replace(/\s+/g, '_').toLowerCase()}`; | |
| const existing = this.gaps.get(gapId); | |
| if (existing) { | |
| // Increment frequency | |
| existing.frequency++; | |
| existing.lastSeen = new Date().toISOString(); | |
| if (!existing.exampleQuestions.includes(userMessage)) { | |
| existing.exampleQuestions = [...existing.exampleQuestions.slice(-4), userMessage]; | |
| } | |
| // Upgrade priority if frequent enough | |
| if (existing.frequency >= 10 && existing.priority !== 'high') { | |
| existing.priority = 'high'; | |
| } else if (existing.frequency >= 5 && existing.priority === 'low') { | |
| existing.priority = 'medium'; | |
| } | |
| this.gaps.set(gapId, existing); | |
| detectedGaps.push(existing); | |
| } else { | |
| // New gap detected | |
| const newGap: KnowledgeGap = { | |
| id: gapId, | |
| topic: topicDef.topic, | |
| topicAr: topicDef.topicAr, | |
| category: topicDef.category, | |
| frequency: 1, | |
| firstSeen: new Date().toISOString(), | |
| lastSeen: new Date().toISOString(), | |
| exampleQuestions: [userMessage], | |
| status: 'identified', | |
| priority: 'low' | |
| }; | |
| this.gaps.set(gapId, newGap); | |
| detectedGaps.push(newGap); | |
| } | |
| } | |
| } | |
| if (detectedGaps.length > 0) this.save(); | |
| return detectedGaps; | |
| } | |
| /** | |
| * Get top priority knowledge gaps to address | |
| */ | |
| getTopGaps(limit: number = 5): KnowledgeGap[] { | |
| const allGaps = Array.from(this.gaps.values()) | |
| .filter(g => g.status !== 'resolved'); | |
| // Sort by priority then frequency | |
| const priorityScore = (g: KnowledgeGap) => { | |
| const p = g.priority === 'high' ? 3 : g.priority === 'medium' ? 2 : 1; | |
| return p * 100 + g.frequency; | |
| }; | |
| return allGaps | |
| .sort((a, b) => priorityScore(b) - priorityScore(a)) | |
| .slice(0, limit); | |
| } | |
| /** | |
| * Mark a gap as resolved with a resolution note | |
| */ | |
| resolveGap(gapId: string, resolution: string): void { | |
| const gap = this.gaps.get(gapId); | |
| if (gap) { | |
| gap.status = 'resolved'; | |
| gap.resolution = resolution; | |
| this.gaps.set(gapId, gap); | |
| this.save(); | |
| } | |
| } | |
| /** | |
| * Get summary stats for the learning dashboard | |
| */ | |
| getStats(): { | |
| total: number; | |
| high: number; | |
| medium: number; | |
| low: number; | |
| resolved: number; | |
| topTopics: string[]; | |
| } { | |
| const all = Array.from(this.gaps.values()); | |
| return { | |
| total: all.length, | |
| high: all.filter(g => g.priority === 'high' && g.status !== 'resolved').length, | |
| medium: all.filter(g => g.priority === 'medium' && g.status !== 'resolved').length, | |
| low: all.filter(g => g.priority === 'low' && g.status !== 'resolved').length, | |
| resolved: all.filter(g => g.status === 'resolved').length, | |
| topTopics: this.getTopGaps(3).map(g => g.topicAr) | |
| }; | |
| } | |
| getAllGaps(): KnowledgeGap[] { | |
| return Array.from(this.gaps.values()); | |
| } | |
| private load(): void { | |
| const dir = path.dirname(this.dbPath); | |
| if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); | |
| if (fs.existsSync(this.dbPath)) { | |
| try { | |
| const data = JSON.parse(fs.readFileSync(this.dbPath, 'utf-8')); | |
| for (const gap of data) { | |
| this.gaps.set(gap.id, gap); | |
| } | |
| } catch { /* start fresh */ } | |
| } | |
| } | |
| private save(): void { | |
| const data = Array.from(this.gaps.values()); | |
| fs.writeFileSync(this.dbPath, JSON.stringify(data, null, 2), 'utf-8'); | |
| } | |
| } | |
| export const knowledgeGapTracker = new KnowledgeGapTracker( | |
| process.env.DB_PATH?.replace('memory.json', 'knowledge_gaps.json') || './data/knowledge_gaps.json' | |
| ); | |