diff --git a/desktop/src/lib/active-learning.ts b/desktop/src/lib/active-learning.ts deleted file mode 100644 index 4634431..0000000 --- a/desktop/src/lib/active-learning.ts +++ /dev/null @@ -1,369 +0,0 @@ -/** - * 主动学习引擎 - 从用户交互中学习并改进 Agent 行为 - * - * 提供学习事件记录、模式提取和建议生成功能。 - * Phase 1: 内存存储,Zustand 持久化 - * Phase 2: SQLite + 向量化存储 - */ - -import { - type LearningEvent, - type LearningPattern, - type LearningSuggestion, - type LearningEventType, - type FeedbackSentiment, -} from '../types/active-learning'; -import { generateRandomString } from './crypto-utils'; - -// === 常量 === - -const MAX_EVENTS = 1000; -const PATTERN_CONFIDENCE_THRESHOLD = 0.7; -const SUGGESTION_COOLDOWN_HOURS = 2; - -// === 生成 ID === - -function generateEventId(): string { - return `le-${Date.now()}-${generateRandomString(8)}`; -} - -// === 分析反馈情感 === - -export function analyzeSentiment(text: string): FeedbackSentiment { - const positive = ['好的', '很棒', '谢谢', '完美', 'excellent', '喜欢', '爱了', 'good', 'great', 'nice', '满意']; - const negative = ['不好', '差', '糟糕', '错误', 'wrong', 'bad', '不喜欢', '讨厌', '问题', '失败', 'fail', 'error']; - - const lowerText = text.toLowerCase(); - - if (positive.some(w => lowerText.includes(w.toLowerCase()))) return 'positive'; - if (negative.some(w => lowerText.includes(w.toLowerCase()))) return 'negative'; - return 'neutral'; -} - -// === 分析学习类型 === - -export function analyzeEventType(text: string): LearningEventType { - const lowerText = text.toLowerCase(); - - if (lowerText.includes('纠正') || lowerText.includes('不对') || lowerText.includes('修改')) { - return 'correction'; - } - if (lowerText.includes('喜欢') || lowerText.includes('偏好') || lowerText.includes('风格')) { - return 'preference'; - } - if (lowerText.includes('场景') || lowerText.includes('上下文') || lowerText.includes('情况')) { - return 'context'; - } - if (lowerText.includes('总是') || lowerText.includes('经常') || lowerText.includes('习惯')) { - return 'behavior'; - } - return 'implicit'; -} - -// === 推断偏好 === - -export function inferPreference(feedback: string, sentiment: FeedbackSentiment): string { - if (sentiment === 'positive') { - if (feedback.includes('简洁')) return '用户偏好简洁的回复'; - if (feedback.includes('详细')) return '用户偏好详细的回复'; - if (feedback.includes('快速')) return '用户偏好快速响应'; - return '用户对当前回复风格满意'; - } - if (sentiment === 'negative') { - if (feedback.includes('太长')) return '用户偏好更短的回复'; - if (feedback.includes('太短')) return '用户偏好更详细的回复'; - if (feedback.includes('不准确')) return '用户偏好更准确的信息'; - return '用户对当前回复风格不满意'; - } - return '用户反馈中性'; -} - -// === 学习引擎类 === - -export class ActiveLearningEngine { - private events: LearningEvent[] = []; - private patterns: LearningPattern[] = []; - // Reserved for future learning suggestions feature - private suggestions: LearningSuggestion[] = []; - private initialized: boolean = false; - - constructor() { - this.initialized = true; - } - - /** Get current suggestions (reserved for future use) */ - getSuggestions(): LearningSuggestion[] { - return this.suggestions; - } - - /** Check if engine is initialized */ - isInitialized(): boolean { - return this.initialized; - } - - /** - * 记录学习事件 - */ - recordEvent( - event: Omit - ): LearningEvent { - // 检查重复事件 - const existing = this.events.find(e => - e.agentId === event.agentId && - e.messageId === event.messageId && - e.type === event.type - ); - - if (existing) { - // 更新现有事件 - existing.observation += ' | ' + event.observation; - existing.confidence = (existing.confidence + event.confidence) / 2; - existing.appliedCount++; - return existing; - } - - // 创建新事件 - const newEvent: LearningEvent = { - ...event, - id: generateEventId(), - timestamp: Date.now(), - acknowledged: false, - appliedCount: 0, - }; - - this.events.push(newEvent); - this.extractPatterns(newEvent); - - // 保持事件数量限制 - if (this.events.length > MAX_EVENTS) { - this.events = this.events.slice(-MAX_EVENTS); - } - - return newEvent; - } - - /** - * 从反馈中学习 - */ - learnFromFeedback( - agentId: string, - messageId: string, - feedback: string, - context?: string - ): LearningEvent { - const sentiment = analyzeSentiment(feedback); - const type = analyzeEventType(feedback); - - return this.recordEvent({ - type, - agentId, - messageId, - trigger: context || 'User feedback', - observation: feedback, - context, - inferredPreference: inferPreference(feedback, sentiment), - confidence: sentiment === 'positive' ? 0.8 : sentiment === 'negative' ? 0.5 : 0.3, - }); - } - - /** - * 提取学习模式 - */ - private extractPatterns(event: LearningEvent): void { - // 1. 正面反馈 -> 偏好正面回复 - if (event.observation.includes('谢谢') || event.observation.includes('好的')) { - this.addPattern({ - id: `pat-${Date.now()}-${generateRandomString(8)}`, - type: 'preference', - pattern: 'positive_response_preference', - description: '用户偏好正面回复风格', - examples: [event.observation], - confidence: 0.8, - agentId: event.agentId, - }); - } - - // 2. 纠正 -> 需要更精确 - if (event.type === 'correction') { - this.addPattern({ - id: `pat-${Date.now()}-${generateRandomString(8)}`, - type: 'preference', - pattern: 'precision_preference', - description: '用户对精确性有更高要求', - examples: [event.observation], - confidence: 0.9, - agentId: event.agentId, - }); - } - - // 3. 上下文相关 -> 场景偏好 - if (event.context) { - this.addPattern({ - id: `pat-${Date.now()}-${generateRandomString(8)}`, - type: 'context', - pattern: 'context_aware', - description: 'Agent 需要关注上下文', - examples: [event.context], - confidence: 0.6, - agentId: event.agentId, - }); - } - } - - /** - * 添加学习模式 - */ - private addPattern(pattern: Omit): void { - const existing = this.patterns.find(p => - p.type === pattern.type && - p.pattern === pattern.pattern && - p.agentId === pattern.agentId - ); - - if (existing) { - // 增强置信度 - existing.confidence = Math.min(1, existing.confidence + pattern.confidence * 0.1); - existing.examples.push(pattern.examples[0]); - existing.updatedAt = Date.now(); - } else { - this.patterns.push({ - ...pattern, - updatedAt: Date.now(), - }); - } - } - - /** - * 生成学习建议 - */ - generateSuggestions(agentId: string): LearningSuggestion[] { - const suggestions: LearningSuggestion[] = []; - const now = Date.now(); - - // 获取该 Agent 的模式 - const agentPatterns = this.patterns.filter(p => p.agentId === agentId); - - for (const pattern of agentPatterns) { - // 检查冷却时间 - const hoursSinceUpdate = (now - (pattern.updatedAt || now)) / (1000 * 60 * 60); - if (hoursSinceUpdate < SUGGESTION_COOLDOWN_HOURS) continue; - - // 检查置信度阈值 - if (pattern.confidence < PATTERN_CONFIDENCE_THRESHOLD) continue; - - // 生成建议 - suggestions.push({ - id: `sug-${Date.now()}-${generateRandomString(8)}`, - agentId, - type: pattern.type, - pattern: pattern.pattern, - suggestion: this.generateSuggestionContent(pattern), - confidence: pattern.confidence, - createdAt: now, - expiresAt: new Date(now + 7 * 24 * 60 * 60 * 1000), - dismissed: false, - }); - } - - return suggestions; - } - - /** - * 生成建议内容 - */ - private generateSuggestionContent(pattern: LearningPattern): string { - const templates: Record = { - positive_response_preference: - '用户似乎偏好正面回复。建议在回复时保持积极和确认的语气。', - precision_preference: - '用户对精确性有更高要求。建议在提供信息时更加详细和准确。', - context_aware: - 'Agent 需要关注上下文。建议在回复时考虑对话的背景和历史。', - }; - - return templates[pattern.pattern] || `观察到模式: ${pattern.pattern}`; - } - - /** - * 获取统计信息 - */ - getStats(agentId: string) { - const agentEvents = this.events.filter(e => e.agentId === agentId); - const agentPatterns = this.patterns.filter(p => p.agentId === agentId); - - const eventsByType: Record = { - preference: 0, - correction: 0, - context: 0, - feedback: 0, - behavior: 0, - implicit: 0, - }; - - for (const event of agentEvents) { - eventsByType[event.type]++; - } - - return { - totalEvents: agentEvents.length, - eventsByType, - totalPatterns: agentPatterns.length, - avgConfidence: agentPatterns.length > 0 - ? agentPatterns.reduce((sum, p) => sum + p.confidence, 0) / agentPatterns.length - : 0, - }; - } - - /** - * 获取所有事件 - */ - getEvents(agentId?: string): LearningEvent[] { - if (agentId) { - return this.events.filter(e => e.agentId === agentId); - } - return [...this.events]; - } - - /** - * 获取所有模式 - */ - getPatterns(agentId?: string): LearningPattern[] { - if (agentId) { - return this.patterns.filter(p => p.agentId === agentId); - } - return [...this.patterns]; - } - - /** - * 确认事件 - */ - acknowledgeEvent(eventId: string): void { - const event = this.events.find(e => e.id === eventId); - if (event) { - event.acknowledged = true; - } - } - - /** - * 清除事件 - */ - clearEvents(agentId: string): void { - this.events = this.events.filter(e => e.agentId !== agentId); - this.patterns = this.patterns.filter(p => p.agentId !== agentId); - } -} - -// === 单例实例 === - -let engineInstance: ActiveLearningEngine | null = null; - -export function getActiveLearningEngine(): ActiveLearningEngine { - if (!engineInstance) { - engineInstance = new ActiveLearningEngine(); - } - return engineInstance; -} - -export function resetActiveLearningEngine(): void { - engineInstance = null; -} diff --git a/desktop/src/types/active-learning.ts b/desktop/src/types/active-learning.ts deleted file mode 100644 index 14c6b8b..0000000 --- a/desktop/src/types/active-learning.ts +++ /dev/null @@ -1,59 +0,0 @@ -/** - * 主动学习引擎类型定义 - */ - -export type LearningEventType = - | 'preference' - | 'correction' - | 'context' - | 'feedback' - | 'behavior' - | 'implicit'; - -export type FeedbackSentiment = 'positive' | 'negative' | 'neutral'; - -export interface LearningEvent { - id: string; - type: LearningEventType; - agentId: string; - messageId: string; - timestamp: number; - trigger: string; - observation: string; - context?: string; - inferredPreference?: string; - confidence: number; - acknowledged: boolean; - appliedCount: number; -} - -export interface LearningPattern { - id: string; - type: LearningEventType; - pattern: string; - description: string; - examples: string[]; - confidence: number; - agentId: string; - updatedAt: number; -} - -export interface LearningSuggestion { - id: string; - agentId: string; - type: LearningEventType; - pattern: string; - suggestion: string; - confidence: number; - createdAt: number; - expiresAt?: Date; - dismissed: boolean; -} - -export interface ActiveLearningState { - events: LearningEvent[]; - patterns: LearningPattern[]; - suggestions: LearningSuggestion[]; - isEnabled: boolean; - lastProcessed: number; -}