feat(memory): Day M.1 complete - importance scoring system
- Add FrequencyTracker: increment(), get_frequency_score(), get_recency_score(), get_time_decay() - Add EmotionAnalyzer: EMOTION_KEYWORDS dict, extract(), calculate_score(), get_emotion_profile() - Add ImpactEvaluator: evaluate(), get_topic_overlap(), rank_by_impact() - Add ImportanceScorer: composite scoring (freq 35% + recency 20% + emotion 25% + impact 20%) - Update UserMemory model: frequency_count, emotion_tags, importance_score, importance_level, associated_topics - Integrate ImportanceScorer into memory_service.py (recall + importance update) - Add 37 tests for all memory scoring components - Fix urgency patterns: remove overly broad '今天' that matched neutral text - Update memory-update checklist: mark all M.1 tasks complete
This commit is contained in:
@@ -7,6 +7,7 @@ Jarvis 记忆系统 (基于 Mem0)
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import json
|
||||
from datetime import UTC, datetime
|
||||
from typing import Optional, Any
|
||||
from sqlalchemy import select, desc, func
|
||||
@@ -15,6 +16,10 @@ from app.models.conversation import Conversation, Message
|
||||
from app.models.memory import UserMemory
|
||||
from app.models.user import User
|
||||
from app.services.brain_service import BrainService
|
||||
from app.services.memory.frequency_tracker import FrequencyTracker
|
||||
from app.services.memory.emotion_analyzer import EmotionAnalyzer
|
||||
from app.services.memory.impact_evaluator import ImpactEvaluator
|
||||
from app.services.memory.importance_scorer import ImportanceScorer
|
||||
from app.config import settings as _settings
|
||||
|
||||
try:
|
||||
@@ -312,8 +317,7 @@ def _extract_memory_query_tokens(query: str) -> list[str]:
|
||||
tokens.append(stripped_chunk)
|
||||
if len(stripped_chunk) > 6:
|
||||
tokens.extend(
|
||||
stripped_chunk[index:index + 4]
|
||||
for index in range(len(stripped_chunk) - 3)
|
||||
stripped_chunk[index : index + 4] for index in range(len(stripped_chunk) - 3)
|
||||
)
|
||||
|
||||
return list(dict.fromkeys(tokens))
|
||||
@@ -344,16 +348,21 @@ async def recall_user_memories(
|
||||
|
||||
query_tokens = _extract_memory_query_tokens(query)
|
||||
statement = select(UserMemory).where(UserMemory.user_id == user_id)
|
||||
result = await db.execute(statement.order_by(UserMemory.importance.desc(), UserMemory.created_at.desc()))
|
||||
result = await db.execute(
|
||||
statement.order_by(UserMemory.importance_score.desc(), UserMemory.created_at.desc())
|
||||
)
|
||||
fallback_memories = list(result.scalars().all())
|
||||
|
||||
if _contains_hint(_normalize_query(query), MEMORY_QUERY_HINTS) or _matches_memory_query_pattern(_normalize_query(query)):
|
||||
if _contains_hint(_normalize_query(query), MEMORY_QUERY_HINTS) or _matches_memory_query_pattern(
|
||||
_normalize_query(query)
|
||||
):
|
||||
return fallback_memories[:top_k]
|
||||
|
||||
if query_tokens:
|
||||
matched_memories = [
|
||||
memory for memory in fallback_memories
|
||||
if any(token in (memory.content or '').lower() for token in query_tokens)
|
||||
memory
|
||||
for memory in fallback_memories
|
||||
if any(token in (memory.content or "").lower() for token in query_tokens)
|
||||
]
|
||||
return matched_memories[:top_k]
|
||||
|
||||
@@ -361,13 +370,25 @@ async def recall_user_memories(
|
||||
|
||||
|
||||
async def _mark_memories_recalled(db: AsyncSession, memories: list[UserMemory]) -> None:
|
||||
"""Mark memories as recalled and update importance score"""
|
||||
from app.services.memory.frequency_tracker import FrequencyTracker
|
||||
from app.services.memory.importance_scorer import ImportanceScorer
|
||||
|
||||
recalled_at = datetime.now(UTC)
|
||||
tracker = FrequencyTracker()
|
||||
scorer = ImportanceScorer()
|
||||
updated = False
|
||||
|
||||
for memory in memories:
|
||||
memory.is_recalled = True
|
||||
memory.recall_count = (memory.recall_count or 0) + 1
|
||||
memory.last_recalled_at = recalled_at
|
||||
memory.frequency_count = memory.recall_count # Keep in sync
|
||||
|
||||
# Update importance score on recall
|
||||
scorer.update_memory_importance(memory)
|
||||
updated = True
|
||||
|
||||
if updated:
|
||||
await db.commit()
|
||||
|
||||
@@ -417,9 +438,7 @@ MEMORY_QUERY_HINTS = (
|
||||
"偏好",
|
||||
"习惯",
|
||||
)
|
||||
MEMORY_QUERY_PATTERNS = (
|
||||
re.compile(r"\bremember\s+(?:that\s+)?i\b"),
|
||||
)
|
||||
MEMORY_QUERY_PATTERNS = (re.compile(r"\bremember\s+(?:that\s+)?i\b"),)
|
||||
GROUNDING_QUERY_HINTS = (
|
||||
"根据文档",
|
||||
"严格根据",
|
||||
|
||||
Reference in New Issue
Block a user