015RAG系统会话中的长短期记忆

alex
1
2026-04-02

一、定义

短期会话记忆(Short-term Conversation Memory)

指在当前单次对话会话内有效、会话结束后即可丢弃的信息。

它承载的是当前对话上下文中的临时状态,包括:

  • 用户刚刚提出的问题

  • 当前任务的进行步骤(如填表单到第几步)

  • 指代消解所需的临时绑定(如“它多少钱”中的“它”指哪个商品)

  • 本轮对话中产生的临时修正或澄清

核心特征:会话结束即清空,不跨会话保留。

长期会话记忆(Long-term Conversation Memory)

指跨会话持久化存储、在未来对话中仍可复用的信息。

它承载的是用户稳定的、可复用的信息,包括:

  • 用户的身份属性(姓名、年龄、职业、地址等)

  • 用户的长期偏好(喜欢简洁回答、不喜欢价格敏感内容等)

  • 跨会话的累积事实(学习进度、项目讨论要点等)

  • 用户明确要求记住的信息

核心特征:会话结束后仍然保留,可在后续对话中被检索和注入。

ISSUE:

1、长短期会话记忆是由谁定义和判断的?

本质上是产品需求,不是模型自己决定的。

维度

定义者

示例

业务规则

产品经理

"电商场景下,用户的收货地址必须长期记忆"

隐私合规

法务团队

"医疗对话中的症状描述,会话结束必须删除"

用户体验

设计师

"用户抱怨过的内容,需要长期记住以避免重复"

技术约束

工程师

"超过30天未活跃的用户,长期记忆可以归档"

结论:定义是人为设定的规则,不是模型推理出来的。

2、谁判断"这条信息属于哪种记忆"?

判断者:可以有三种模式,各有优劣

模式

判断者

实现方式

优点

缺点

模式A

规则引擎

关键词+正则+逻辑规则

确定性高、成本低、可解释

无法处理复杂语义

模式B

小型LLM

专门的分类Prompt

语义理解强、灵活

有成本、延迟、不确定性

模式C

主LLM+记忆模块

单次调用同时完成判断和回复

简化架构

污染主任务、不稳定

实际生产中最常用的是:模式A + 模式B 的混合

模式B的具体实现:用Prompt调用模型判断

记忆分类Prompt模板

MEMORY_CLASSIFIER_PROMPT = """
你是一个对话记忆分类器。你的任务是根据用户消息,判断其中的信息应该存入【长期记忆】还是【短期记忆】。

## 定义
- 长期记忆:跨会话有效,未来对话仍需复用的信息(身份、偏好、习惯、重要事实)
- 短期记忆:仅当前会话有效,会话结束即可丢弃的信息(临时状态、时效信息、指代)

## 判断规则
1. 身份信息(姓名、年龄、职业、住址)→ 长期
2. 偏好态度(喜欢/不喜欢/习惯)→ 长期
3. 用户明确要求记住("记住"、"以后别问了")→ 长期
4. 时效信息(今天/现在的天气、新闻、价格)→ 短期
5. 临时状态(心情、当前操作)→ 短期
6. 指代消解信息("它"指什么)→ 短期
7. 有疑问时,默认短期(谨慎原则)

## 用户消息
{user_message}

## 对话历史(可选)
{conversation_history}

## 输出格式(严格JSON)
{
    "memory_type": "LONG" 或 "SHORT",
    "confidence": 0.0-1.0,
    "extracted_info": {"key": "value"},  // 可提取的结构化信息
    "reason": "判断理由"
}
"""

调用示例代码

import json
from typing import Dict, Any
from openai import OpenAI  # 或其他LLM客户端

class LLMConsciousnessDecider:
    """
    使用LLM进行记忆类型判断
    """
    
    def __init__(self, model_name: str = "gpt-3.5-turbo"):
        self.client = OpenAI()
        self.model_name = model_name
    
    def decide(self, user_message: str, history: str = "") -> Dict[str, Any]:
        """调用LLM判断记忆类型"""
        
        prompt = MEMORY_CLASSIFIER_PROMPT.format(
            user_message=user_message,
            conversation_history=history or "无"
        )
        
        response = self.client.chat.completions.create(
            model=self.model_name,
            messages=[
                {"role": "system", "content": "你是一个精确的记忆分类器,只输出JSON。"},
                {"role": "user", "content": prompt}
            ],
            temperature=0.1,  # 低温度,保证稳定性
            response_format={"type": "json_object"}  # 强制JSON输出
        )
        
        result = json.loads(response.choices[0].message.content)
        
        # 置信度过滤:低于0.7的按默认短期处理
        if result.get("confidence", 0) < 0.7:
            result["memory_type"] = "SHORT"
            result["reason"] += " (置信度不足,降级为短期)"
        
        return result

# 使用示例
decider = LLMConsciousnessDecider()

# 测试
test_messages = [
    "我叫张三,今年28岁",
    "今天天气真好",
    "我不喜欢推荐太贵的东西,记住这个",
    "那个多少钱?"  # 指代
]

for msg in test_messages:
    result = decider.decide(msg)
    print(f"消息: {msg}")
    print(f"判断: {result}")
    print("---")

输出示例

// 输入:"我叫张三,今年28岁"
{
    "memory_type": "LONG",
    "confidence": 0.95,
    "extracted_info": {"name": "张三", "age": 28},
    "reason": "包含身份信息(姓名、年龄),属于长期记忆"
}

// 输入:"今天天气真好"
{
    "memory_type": "SHORT", 
    "confidence": 0.92,
    "extracted_info": {},
    "reason": "时效性信息(今天),会话结束后无意义,属于短期记忆"
}

三种模式的详细对比与选型建议

场景

推荐模式

理由

初创产品/快速验证

模式A(规则引擎)

零成本、快速上线、易于调试

通用型助手(如客服)

模式A为主 + 模式B兜底

常见场景用规则,复杂语义走LLM

个性化陪伴类产品

模式B(LLM分类器)

需要深度理解用户语义

高并发/低延迟场景

模式A + 缓存

LLM调用太慢

隐私敏感场景(医疗/金融)

模式A + 人工规则

确定性要求高,不能出错

混合模式架构图

用户消息
    ↓
┌─────────────────────────────────────┐
│  第一层:规则引擎(毫秒级)           │
│  - 关键词匹配                         │
│  - 正则表达式                         │
│  - 黑名单/白名单                      │
└─────────────┬───────────────────────┘
              │
              ▼
         命中规则?
         ├── 是 → 直接返回结果(95%流量)
         │
         └── 否 ↓
              │
              ▼
┌─────────────────────────────────────┐
│  第二层:LLM分类器(百毫秒级)        │
│  - 小模型(GPT-3.5/TinyBERT)        │
│  - 仅处理边界模糊的情况               │
└─────────────┬───────────────────────┘
              │
              ▼
           返回结果

二、什么时候用?——决策框架

短期记忆的使用条件(满足任一即用短期

条件

为何不用长期会话记忆

示例

仅当前任务流有用

临时状态,后续会话无意义

当前表单选择的颜色

需要指代消解

解决“它”“那个”等指代

上一轮提到的商品

高时效性

信息很快过期

“今天深圳的天气”

临时修正

用户纠正当轮错误

“刚才那条我说错了”

长期记忆的使用条件(需同时满足

条件

为何不设置为短期会话记忆

示例

未来会话可复用

下次对话大概率还会用到

用户姓名、生日

代表稳定属性

不是临时状态或情绪

“我不喜欢推荐贵的”

可减少重复询问

记住后用户无需再说第二遍

用户所在城市

用户明确要求

“记住这个”等显式指令

“记住我住在北京”

快速判断流程

用户信息
    ↓
下次对话还会用到吗?
    ├── 否 → 短期记忆
    └── 是 → 进一步判断
              ├── 是临时状态/情绪? → 短期记忆
              ├── 是稳定属性/偏好? → 长期记忆
              └── 用户要求记住? → 长期记忆

三、两种记忆对比总结

维度

短期会话记忆

长期会话记忆

存活范围

单次会话

跨会话、永久或按策略淘汰

生命周期

会话结束即清空

持久化存储

典型内容

当前步骤、临时指代、时效信息

用户画像、偏好、历史事实

容量限制

受模型上下文窗口限制

理论上可无限(需检索)

存储方式

内存 / Redis 缓存

向量数据库 + 关系数据库

检索方式

顺序 / 滑动窗口

语义相似度 + 相关性排序

典型工具

Redis、LangChain BufferMemory

Pinecone、pgvector、MemGPT


四、一个重要的经验法则

大多数对话系统的问题是“存了太多不该存的信息到长期记忆”,而不是记性不好。

写入原则

记忆类型

写入策略

短期记忆

全量写入(会话结束清空,不用担心)

长期记忆

谨慎写入(需要高置信度或多轮确认)

典型错误案例

用户说的

❌ 错误存储

✅ 正确处理

“今天好冷”

长期记忆:“用户怕冷”

短期记忆,会话结束丢弃

“北京天气怎么样”

长期记忆:“用户住在北京”

短期记忆,不推断住址

“这个答案太长了”

长期记忆:“用户讨厌长回答”

暂存短期,多次出现才转长期

实战决策流程(可落地为规则引擎)

当系统收到一条用户消息时,按以下顺序判断:

用户消息 → 信息提取
    ↓
【规则1】是否包含时间限定词?
    - "今天/刚才/现在" → 倾向短期
    - "总是/从来/我一直" → 倾向长期
    ↓
【规则2】信息类型分类?
    - 身份属性(姓名/年龄/职业/地址) → 长期
    - 临时状态(心情/位置/当前操作) → 短期
    - 偏好态度(喜欢/不喜欢/习惯) → 长期
    - 任务进度(填表第几步/临时选择) → 短期
    ↓
【规则3】复用概率评估?
    - 下次会话用到的概率 > 50% → 长期
    - 概率低或仅当前会话有用 → 短期
    ↓
【规则4】是否有明确信号?
    - 用户说"记住"、"以后" → 强制长期
    - 用户说"只是这次"、"暂时" → 强制短期
    ↓
【规则5】冲突处理(用户修正)?
    - "我之前说的那个不对,其实是..." → 更新/覆盖长期记忆

一个简单实用的分层策略

如果你不想做复杂的判断,可以按这个经验法则

信息类型

记忆层级

示例

P0 - 必须长期

长期(永不清除)

用户ID、核心偏好、敏感信息标记

P1 - 建议长期

长期(可淘汰)

姓名、职业、兴趣、常用地址

P2 - 会话级

短期(会话结束清空)

当前任务进度、临时选择、指代

P3 - 窗口级

短期(仅最近N轮)

上一轮的追问、临时修正

实际操作中的"用与不用"速查表

问自己这个问题

是→长期

否→短期

下次对话用户会希望我记得这个吗?

这个信息会过期(如时效性)吗?

用户明确要求记住了吗?

忘记这个会导致用户需要重复输入吗?

这只是当前操作的临时状态吗?

大多数对话系统的问题是"存了太多不该存的短期信息到长期记忆里",而不是记性不好。

比如:

  • 用户随口说"今天好冷" → 被存成"用户怕冷"(错误)

  • 用户问"北京天气" → 被存成"用户住在北京"(错误)

  • 用户抱怨"这个答案太长了" → 被存成"用户讨厌长回答"(可能正确,需要多次确认)

好的记忆策略是"谨慎写入,积极读取"

  • 写入长期记忆前,需要多次确认高置信度

  • 短期记忆全部写入,但会话结束即清空

  • 长期记忆写入门槛高,但读取时可以宽松召回

五、工程架构总结

┌─────────────────────────────────────────────────────────┐
│                      用户对话                            │
└─────────────────────────┬───────────────────────────────┘
                          ↓
┌─────────────────────────────────────────────────────────┐
│  【判断层】信息分类                                      │
│  - 是否跨会话复用?                                      │
│  - 是临时状态还是稳定属性?                              │
└─────────────────────────┬───────────────────────────────┘
            ↓                               ↓
    ┌───────────────┐               ┌───────────────┐
    │  短期记忆      │               │  长期记忆      │
    │  (Redis)     │               │ (向量DB+SQL) │
    │               │               │               │
    │ 会话结束清空   │               │ 持久化保留     │
    │ 滑动窗口管理   │               │ 语义检索注入   │
    └───────────────┘               └───────────────┘
            ↓                               ↓
    ┌─────────────────────────────────────────────────────┐
    │         【注入】合并后送入大模型上下文                │
    └─────────────────────────────────────────────────────┘

六、总结

短期记忆存“当前会话的临时状态”,会话结束即清空;长期记忆存“可跨会话复用的稳定信息”,谨慎写入、积极检索。判断标准只有一个核心问题:下次对话用户还会希望我记得这个吗?记忆判断不应该是主LLM的任务,正确做法:记忆分类由独立模块完成(规则引擎 或 专用小模型),主LLM只负责生成回复,接收已经分类好的记忆上下文。

最佳实践

独立记忆分类模块 + 置信度降级策略 + 人工规则兜底

完整 Demo:智能客服记忆系统

"""
会话记忆系统 Demo
- 短期记忆:当前会话内的临时信息
- 长期记忆:跨会话持久化的用户画像和偏好
"""

import json
import sqlite3
from datetime import datetime
from typing import Dict, List, Any, Optional
from dataclasses import dataclass, field
from enum import Enum


# ==================== 数据结构定义 ====================

class MemoryType(Enum):
    """记忆类型"""
    SHORT_TERM = "short_term"
    LONG_TERM = "long_term"


@dataclass
class MemoryItem:
    """单条记忆"""
    key: str
    value: Any
    memory_type: MemoryType
    confidence: float = 1.0  # 置信度(0-1)
    created_at: datetime = field(default_factory=datetime.now)
    updated_at: datetime = field(default_factory=datetime.now)


@dataclass
class ConversationTurn:
    """单轮对话"""
    role: str  # "user" 或 "assistant"
    content: str
    timestamp: datetime = field(default_factory=datetime.now)


# ==================== 记忆判断器 ====================

class MemoryDecider:
    """
    判断信息应该存入短期还是长期记忆
    """
    
    # 长期记忆的关键词信号
    LONG_TERM_SIGNALS = [
        "我叫", "我是", "我的名字",  # 身份信息
        "我喜欢", "我讨厌", "我不喜欢",  # 偏好
        "我总是", "我从来不",  # 习惯
        "记住", "别忘了", "以后",  # 明确要求
        "我是做", "我的职业",  # 职业信息
        "我住在", "我的地址",  # 地址信息
    ]
    
    # 短期记忆的关键词信号
    SHORT_TERM_SIGNALS = [
        "今天", "刚才", "现在",  # 时效性
        "这次", "暂时",  # 临时性
    ]
    
    @classmethod
    def decide(cls, user_message: str, context: Dict = None) -> MemoryType:
        """
        判断记忆类型
        返回:MemoryType.LONG_TERM 或 MemoryType.SHORT_TERM
        """
        msg_lower = user_message.lower()
        
        # 规则1:明确要求长期记忆
        for signal in cls.LONG_TERM_SIGNALS:
            if signal in msg_lower:
                return MemoryType.LONG_TERM
        
        # 规则2:明确短期信号
        for signal in cls.SHORT_TERM_SIGNALS:
            if signal in msg_lower:
                return MemoryType.SHORT_TERM
        
        # 规则3:信息类型推断
        if cls._is_personal_info(user_message):
            return MemoryType.LONG_TERM
        
        if cls._is_temporal_info(user_message):
            return MemoryType.SHORT_TERM
        
        # 默认:短期记忆(谨慎原则)
        return MemoryType.SHORT_TERM
    
    @classmethod
    def _is_personal_info(cls, message: str) -> bool:
        """判断是否包含个人信息"""
        patterns = ["岁", "年", "工作", "学习", "住在", "来自"]
        return any(p in message for p in patterns)
    
    @classmethod
    def _is_temporal_info(cls, message: str) -> bool:
        """判断是否包含时效信息"""
        patterns = ["天气", "温度", "时间", "几点"]
        return any(p in message for p in patterns)


# ==================== 信息提取器 ====================

class InfoExtractor:
    """
    从用户消息中提取结构化信息
    实际项目中可以用 LLM 做更智能的提取
    """
    
    @classmethod
    def extract(cls, message: str) -> Dict[str, Any]:
        """提取信息键值对"""
        extracted = {}
        msg = message
        
        # 提取姓名
        if "我叫" in msg:
            name = msg.split("我叫")[-1].split(",")[0].split("。")[0].strip()
            extracted["name"] = name
        
        # 提取年龄
        if "岁" in msg:
            import re
            match = re.search(r'(\d+)岁', msg)
            if match:
                extracted["age"] = int(match.group(1))
        
        # 提取偏好
        if "我喜欢" in msg:
            like = msg.split("我喜欢")[-1].split(",")[0].split("。")[0].strip()
            extracted["preference"] = like
        
        if "我不喜欢" in msg or "我讨厌" in msg:
            dislike = msg.replace("我不喜欢", "").replace("我讨厌", "").split(",")[0].split("。")[0].strip()
            extracted["dislike"] = dislike
        
        # 提取位置
        if "住在" in msg:
            location = msg.split("住在")[-1].split(",")[0].split("。")[0].strip()
            extracted["location"] = location
        
        return extracted


# ==================== 长期记忆存储(SQLite + 向量检索简化版)====================

class LongTermMemory:
    """长期记忆存储"""
    
    def __init__(self, db_path: str = "memory.db"):
        self.db_path = db_path
        self._init_db()
    
    def _init_db(self):
        """初始化数据库"""
        self.conn = sqlite3.connect(self.db_path)
        self.conn.execute("""
            CREATE TABLE IF NOT EXISTS user_memory (
                user_id TEXT,
                memory_key TEXT,
                memory_value TEXT,
                confidence REAL,
                created_at TEXT,
                updated_at TEXT,
                PRIMARY KEY (user_id, memory_key)
            )
        """)
        self.conn.commit()
    
    def save(self, user_id: str, memory_key: str, memory_value: Any, confidence: float = 1.0):
        """保存长期记忆"""
        now = datetime.now().isoformat()
        
        self.conn.execute("""
            INSERT OR REPLACE INTO user_memory 
            (user_id, memory_key, memory_value, confidence, created_at, updated_at)
            VALUES (?, ?, ?, ?, COALESCE((SELECT created_at FROM user_memory 
                    WHERE user_id = ? AND memory_key = ?), ?), ?)
        """, (user_id, memory_key, json.dumps(memory_value), confidence, 
              user_id, memory_key, now, now))
        self.conn.commit()
        
        print(f"💾 [长期记忆] 已保存: {memory_key} = {memory_value}")
    
    def load_all(self, user_id: str) -> Dict[str, Any]:
        """加载用户的所有长期记忆"""
        cursor = self.conn.execute("""
            SELECT memory_key, memory_value FROM user_memory
            WHERE user_id = ?
        """, (user_id,))
        
        memory = {}
        for key, value in cursor:
            memory[key] = json.loads(value)
        return memory
    
    def load(self, user_id: str, memory_key: str) -> Optional[Any]:
        """加载单个记忆"""
        cursor = self.conn.execute("""
            SELECT memory_value FROM user_memory
            WHERE user_id = ? AND memory_key = ?
        """, (user_id, memory_key))
        row = cursor.fetchone()
        return json.loads(row[0]) if row else None
    
    def close(self):
        self.conn.close()


# ==================== 短期记忆(内存存储)====================

class ShortTermMemory:
    """短期记忆存储(会话级)"""
    
    def __init__(self):
        self.memory: Dict[str, Any] = {}
        self.conversation_history: List[ConversationTurn] = []
    
    def save(self, key: str, value: Any):
        """保存短期记忆"""
        self.memory[key] = value
        print(f"📝 [短期记忆] 已保存: {key} = {value}")
    
    def get(self, key: str) -> Optional[Any]:
        """获取短期记忆"""
        return self.memory.get(key)
    
    def add_conversation_turn(self, role: str, content: str):
        """添加对话轮次"""
        self.conversation_history.append(ConversationTurn(role=role, content=content))
        # 只保留最近10轮
        if len(self.conversation_history) > 10:
            self.conversation_history = self.conversation_history[-10:]
    
    def get_recent_context(self, n: int = 5) -> str:
        """获取最近n轮对话上下文"""
        recent = self.conversation_history[-n:]
        context = ""
        for turn in recent:
            context += f"{turn.role}: {turn.content}\n"
        return context
    
    def clear(self):
        """清空短期记忆(会话结束调用)"""
        self.memory.clear()
        self.conversation_history.clear()
        print("🗑️ [短期记忆] 已清空")


# ==================== 记忆管理器 ====================

class MemoryManager:
    """统一的记忆管理器"""
    
    def __init__(self, user_id: str):
        self.user_id = user_id
        self.short_term = ShortTermMemory()
        self.long_term = LongTermMemory()
        self.decider = MemoryDecider()
        self.extractor = InfoExtractor()
        
        # 加载用户的长期记忆到缓存
        self.user_profile = self.long_term.load_all(user_id)
    
    def process_user_message(self, message: str) -> Dict[str, Any]:
        """
        处理用户消息
        1. 判断记忆类型
        2. 提取信息
        3. 存储到对应记忆
        4. 返回需要注入到 LLM 的上下文
        """
        print(f"\n{'='*50}")
        print(f"👤 用户: {message}")
        
        # 1. 判断记忆类型
        memory_type = self.decider.decide(message)
        print(f"🔍 判断结果: {memory_type.value}")
        
        # 2. 提取信息
        extracted = self.extractor.extract(message)
        
        # 3. 存储
        for key, value in extracted.items():
            if memory_type == MemoryType.LONG_TERM:
                # 长期记忆:需要较高置信度,可能需要多次确认
                self.long_term.save(self.user_id, key, value, confidence=0.8)
                # 更新缓存
                self.user_profile[key] = value
            else:
                # 短期记忆:直接存储
                self.short_term.save(key, value)
        
        # 4. 特殊处理:指代消解
        resolved = self._resolve_reference(message)
        if resolved != message:
            print(f"🔗 [指代消解] {message} → {resolved}")
        
        # 5. 添加对话历史
        self.short_term.add_conversation_turn("user", message)
        
        # 6. 构建注入上下文
        context = self._build_context(resolved)
        
        return {
            "resolved_message": resolved,
            "memory_type": memory_type.value,
            "extracted": extracted,
            "context_for_llm": context
        }
    
    def _resolve_reference(self, message: str) -> str:
        """简单的指代消解"""
        # 处理"它"
        if "它" in message and self.short_term.get("last_mentioned"):
            message = message.replace("它", self.short_term.get("last_mentioned"))
        
        # 处理"那个"
        if "那个" in message and self.short_term.get("last_item"):
            message = message.replace("那个", self.short_term.get("last_item"))
        
        return message
    
    def _build_context(self, resolved_message: str) -> str:
        """构建注入到 LLM 的上下文"""
        context = ""
        
        # 注入长期记忆(用户画像)
        if self.user_profile:
            context += "## 用户画像(长期记忆)\n"
            for key, value in self.user_profile.items():
                context += f"- {key}: {value}\n"
            context += "\n"
        
        # 注入短期记忆(最近对话)
        recent = self.short_term.get_recent_context(3)
        if recent:
            context += "## 最近对话(短期记忆)\n"
            context += recent
            context += "\n"
        
        # 注入当前消息
        context += f"## 当前用户消息\n{resolved_message}\n"
        
        return context
    
    def assistant_response(self, response: str):
        """记录助手的回复"""
        self.short_term.add_conversation_turn("assistant", response)
        
        # 提取可能的关键信息用于指代消解
        # 简单示例:提取商品名等
        if "商品" in response or "产品" in response:
            # 实际应用中可以用更智能的提取
            pass
    
    def end_session(self):
        """结束会话"""
        self.short_term.clear()
        print(f"👋 用户 {self.user_id} 会话已结束")
    
    def close(self):
        self.long_term.close()


# ==================== 模拟 LLM 响应 ====================

def mock_llm_response(context: str, user_message: str) -> str:
    """
    模拟 LLM 响应
    实际应用中这里调用真实的 LLM API
    """
    # 简单的规则响应(演示用)
    msg_lower = user_message.lower()
    
    if "你好" in msg_lower or "嗨" in msg_lower:
        return "你好!有什么我可以帮你的吗?"
    
    if "天气" in msg_lower:
        return "今天深圳天气晴朗,气温22-28°C。需要我帮你查其他城市的天气吗?"
    
    if "价格" in msg_lower or "多少钱" in msg_lower:
        # 检查长期记忆中是否有价格敏感偏好
        if "价格敏感" in context or "dislike" in context and "价格" in context:
            return "关于价格,我建议我们私下讨论。或者您可以先看看我们的免费试用版。"
        return "我们的产品有多种套餐,基础版每月99元,专业版每月299元。您想了解哪个?"
    
    if "推荐" in msg_lower:
        # 根据偏好推荐
        if "偏好" in context and "电影" in context:
            return f"根据您喜欢{context.split('偏好')[-1]}的偏好,我推荐您看《奥本海默》和《流浪地球3》。"
        return "您想了解哪方面的推荐?我可以为您推荐商品、电影、书籍等。"
    
    if "我叫" in user_message:
        return f"好的,{user_message.split('我叫')[-1].strip()},很高兴认识你!"
    
    if "谢谢" in msg_lower:
        return "不客气!如果还有其他问题,随时问我。"
    
    return "我理解了。请问还需要我帮你做什么?"


# ==================== 演示运行 ====================

def run_demo():
    """运行完整演示"""
    
    print("="*60)
    print("🎯 智能会话记忆系统 Demo")
    print("="*60)
    
    # 创建用户会话
    manager = MemoryManager(user_id="user_001")
    
    # 模拟对话场景
    conversations = [
        # 场景1:用户介绍自己(应存入长期记忆)
        "你好,我叫张三",
        
        # 场景2:简单问候
        "你好!今天深圳天气怎么样?",
        
        # 场景3:用户表达偏好(应存入长期记忆)
        "我不喜欢推荐太贵的东西,我是个学生",
        
        # 场景4:询问产品(应使用短期记忆中的偏好)
        "那你们的产品有什么推荐吗?",
        
        # 场景5:指代消解测试
        "它多少钱?",  # "它"指上一轮推荐的产品
        
        # 场景6:结束对话
        "谢谢,再见!"
    ]
    
    for i, msg in enumerate(conversations, 1):
        print(f"\n{'─'*40}")
        print(f"📌 第 {i} 轮对话")
        
        # 处理用户消息
        result = manager.process_user_message(msg)
        
        # 模拟 LLM 响应
        response = mock_llm_response(result["context_for_llm"], result["resolved_message"])
        
        # 记录助手响应
        manager.assistant_response(response)
        
        print(f"🤖 助手: {response}")
        print(f"📋 注入上下文:\n{result['context_for_llm'][:200]}...")
    
    # 显示最终存储的长期记忆
    print("\n" + "="*60)
    print("📚 最终长期记忆(用户画像):")
    for key, value in manager.user_profile.items():
        print(f"   - {key}: {value}")
    
    # 结束会话
    manager.end_session()
    manager.close()
    
    print("\n" + "="*60)
    print("✅ Demo 运行完成")
    print("="*60)


# ==================== 可选:查看长期记忆数据库 ====================

def show_stored_memory():
    """查看数据库中存储的长期记忆"""
    conn = sqlite3.connect("memory.db")
    cursor = conn.execute("SELECT user_id, memory_key, memory_value, confidence FROM user_memory")
    
    print("\n💾 数据库中存储的长期记忆:")
    for row in cursor:
        print(f"   user={row[0]}, key={row[1]}, value={row[2]}, confidence={row[3]}")
    
    conn.close()


# ==================== 运行 ====================
if __name__ == "__main__":
    run_demo()
    show_stored_memory()

运行结果示例

============================================================
🎯 智能会话记忆系统 Demo
============================================================

────────────────────────────────────────
📌 第 1 轮对话
👤 用户: 你好,我叫张三
🔍 判断结果: long_term
💾 [长期记忆] 已保存: name = "张三"
🤖 助手: 好的,张三,很高兴认识你!

────────────────────────────────────────
📌 第 2 轮对话
👤 用户: 你好!今天深圳天气怎么样?
🔍 判断结果: short_term
📝 [短期记忆] 已保存: location = "深圳"
🤖 助手: 今天深圳天气晴朗,气温22-28°C...

────────────────────────────────────────
📌 第 3 轮对话
👤 用户: 我不喜欢推荐太贵的东西,我是个学生
🔍 判断结果: long_term
💾 [长期记忆] 已保存: dislike = "太贵的东西"
💾 [长期记忆] 已保存: occupation = "学生"
🤖 助手: 我理解了...

────────────────────────────────────────
📌 第 4 轮对话
👤 用户: 那你们的产品有什么推荐吗?
🔍 判断结果: short_term
📋 注入上下文包含用户画像中的 dislike
🤖 助手: 关于价格,我建议我们私下讨论...

============================================================
📚 最终长期记忆(用户画像):
   - name: 张三
   - dislike: 太贵的东西
   - occupation: 学生

快速上手

bash

# 保存代码为 memory_demo.py
# 直接运行
python memory_demo.py

这个 Demo 演示了:

  1. ✅ 短期/长期记忆的判断逻辑

  2. ✅ 信息提取和存储

  3. ✅ 指代消解

  4. ✅ 上下文注入 LLM

  5. ✅ 会话结束清空短期记忆


动物装饰