跳转至

情景与语义记忆

引言

Endel Tulving(1972)将长期记忆分为情景记忆(episodic)、语义记忆(semantic)和程序记忆(procedural)。这一分类为 Agent 记忆系统的设计提供了重要的理论指导。不同类型的记忆服务于不同的目的,需要不同的存储和检索机制。

Tulving 的记忆分类

记忆类型 内容 人类示例 Agent 示例
情景记忆 个人经历和事件 "昨天我去了公园" "用户昨天请求了数据分析"
语义记忆 一般知识和事实 "巴黎是法国首都" "Python 的 list 是可变类型"
程序记忆 技能和操作方式 骑自行车 调用 API 的标准流程

情景记忆(Episodic Memory)

定义与特征

情景记忆记录的是具体的经历和事件,具有以下特征:

  • 时间标记:发生在特定时间
  • 情境依赖:与特定场景相关
  • 自传性:与"我"(Agent 自身)相关
  • 可重放:可以回忆和重新体验

Agent 中的情景记忆

对话历史

最基本的情景记忆——记录 Agent 与用户的每次交互:

class EpisodicMemory:
    def __init__(self, vector_store):
        self.vector_store = vector_store

    def store_episode(self, episode):
        """存储一个交互事件"""
        record = {
            "id": generate_id(),
            "timestamp": datetime.now().isoformat(),
            "user_query": episode["query"],
            "agent_response": episode["response"],
            "tools_used": episode.get("tools", []),
            "outcome": episode.get("outcome", "unknown"),  # success/failure
            "context": episode.get("context", ""),
        }

        # 生成摘要用于嵌入
        summary = f"用户问: {record['user_query']}. Agent 回答后结果: {record['outcome']}"

        self.vector_store.add(
            documents=[summary],
            metadatas=[record],
            ids=[record["id"]]
        )

    def recall(self, query, n=5, time_range=None):
        """回忆相关经历"""
        filters = {}
        if time_range:
            filters["timestamp"] = {"$gte": time_range[0], "$lte": time_range[1]}

        return self.vector_store.query(
            query_texts=[query],
            n_results=n,
            where=filters if filters else None
        )

经验回放(Experience Replay)

借鉴强化学习的概念,Agent 可以从过去的经验中学习:

class ExperienceReplay:
    def __init__(self, memory, llm):
        self.memory = memory
        self.llm = llm

    def learn_from_failures(self, current_task):
        """从过去的失败经验中学习"""
        # 检索类似任务的失败案例
        failures = self.memory.recall(
            query=current_task,
            n=3,
            filters={"outcome": "failure"}
        )

        if failures:
            lessons = self.llm.generate(
                f"分析以下失败案例,提取对当前任务有用的教训:\n"
                f"当前任务: {current_task}\n"
                f"历史失败: {failures}\n"
                f"教训:"
            )
            return lessons
        return None

    def learn_from_successes(self, current_task):
        """从过去的成功经验中学习"""
        successes = self.memory.recall(
            query=current_task,
            n=3,
            filters={"outcome": "success"}
        )

        if successes:
            strategy = self.llm.generate(
                f"基于以下成功案例,为当前任务推荐策略:\n"
                f"当前任务: {current_task}\n"
                f"历史成功: {successes}\n"
                f"推荐策略:"
            )
            return strategy
        return None

Generative Agents 中的记忆流

Park et al.(2023)在 "Generative Agents" 中设计了记忆流(Memory Stream)机制:

class MemoryStream:
    """Generative Agents 风格的记忆流"""

    def __init__(self):
        self.memories = []

    def add_observation(self, description, importance=None):
        """添加观察"""
        if importance is None:
            importance = self.score_importance(description)

        self.memories.append({
            "description": description,
            "timestamp": datetime.now(),
            "importance": importance,  # 1-10
            "last_accessed": datetime.now(),
        })

    def retrieve(self, query, n=10):
        """基于相关性、时效性和重要性的综合检索"""
        scores = []
        for mem in self.memories:
            recency = self.recency_score(mem)
            importance = mem["importance"] / 10.0
            relevance = self.relevance_score(query, mem["description"])

            # 综合评分
            score = recency + importance + relevance
            scores.append((mem, score))

        scores.sort(key=lambda x: x[1], reverse=True)
        return [mem for mem, score in scores[:n]]

    def recency_score(self, memory):
        """时效性评分:指数衰减"""
        hours_ago = (datetime.now() - memory["last_accessed"]).total_seconds() / 3600
        return 0.99 ** hours_ago  # 衰减因子

语义记忆(Semantic Memory)

定义与特征

语义记忆存储的是一般性知识和事实,与具体经历脱钩:

  • 去情境化:不依赖于特定时间和场景
  • 结构化:可以组织为概念网络
  • 可推理:支持逻辑推断

知识图谱作为语义记忆

class SemanticMemory:
    """基于知识图谱的语义记忆"""

    def __init__(self):
        self.triples = []  # (subject, predicate, object)
        self.entity_index = {}  # entity -> related triples

    def add_knowledge(self, subject, predicate, obj, confidence=1.0):
        """添加知识三元组"""
        triple = {
            "subject": subject,
            "predicate": predicate,
            "object": obj,
            "confidence": confidence,
            "source": "observation",
            "updated_at": datetime.now(),
        }
        self.triples.append(triple)

        # 更新索引
        for entity in [subject, obj]:
            if entity not in self.entity_index:
                self.entity_index[entity] = []
            self.entity_index[entity].append(triple)

    def query(self, subject=None, predicate=None, obj=None):
        """查询知识"""
        results = self.triples
        if subject:
            results = [t for t in results if t["subject"] == subject]
        if predicate:
            results = [t for t in results if t["predicate"] == predicate]
        if obj:
            results = [t for t in results if t["object"] == obj]
        return results

    def get_entity_knowledge(self, entity, depth=1):
        """获取实体的相关知识(可多跳)"""
        if depth == 0 or entity not in self.entity_index:
            return []

        direct = self.entity_index[entity]
        if depth == 1:
            return direct

        # 多跳:获取邻居实体的知识
        result = list(direct)
        for triple in direct:
            neighbor = triple["object"] if triple["subject"] == entity else triple["subject"]
            result.extend(self.get_entity_knowledge(neighbor, depth - 1))
        return result

结构化事实存储

class StructuredFactStore:
    """用户相关的结构化事实"""

    def __init__(self):
        self.facts = {}  # category -> list of facts

    def add_fact(self, category, key, value, source="conversation"):
        if category not in self.facts:
            self.facts[category] = {}

        self.facts[category][key] = {
            "value": value,
            "source": source,
            "confidence": 1.0,
            "updated_at": datetime.now(),
        }

    def get_user_profile(self):
        """获取用户画像"""
        return self.facts

    # 使用示例:
    # store.add_fact("preferences", "response_style", "简洁")
    # store.add_fact("background", "programming_language", "Python")
    # store.add_fact("project", "current_task", "构建 RAG 系统")

程序记忆(Procedural Memory)

定义与特征

程序记忆存储的是技能、习惯和操作流程

  • 隐式知识:通常难以用语言描述
  • 自动化:熟练后可以自动执行
  • 抗遗忘:一旦学会很难忘记

Agent 的程序记忆

学习到的工作流

class ProceduralMemory:
    """存储 Agent 学习到的操作流程"""

    def __init__(self, vector_store):
        self.vector_store = vector_store
        self.workflows = {}

    def store_workflow(self, task_type, steps, success_rate=None):
        """存储一个成功的工作流"""
        workflow = {
            "task_type": task_type,
            "steps": steps,
            "success_rate": success_rate,
            "usage_count": 1,
            "created_at": datetime.now().isoformat(),
        }

        self.workflows[task_type] = workflow

        # 同时存入向量数据库以支持语义检索
        description = f"任务类型: {task_type}. 步骤: {' -> '.join(steps)}"
        self.vector_store.add(
            documents=[description],
            metadatas=[workflow],
            ids=[f"workflow_{task_type}"]
        )

    def find_workflow(self, task_description, threshold=0.8):
        """查找适用的工作流"""
        results = self.vector_store.query(
            query_texts=[task_description],
            n_results=3,
        )

        if results and results["distances"][0][0] < threshold:
            return results["metadatas"][0][0]
        return None

Prompt 模板库

class PromptTemplateMemory:
    """存储和复用成功的 prompt 模板"""

    def __init__(self):
        self.templates = {}

    def store_template(self, name, template, performance_score):
        self.templates[name] = {
            "template": template,
            "score": performance_score,
            "usage_count": 0,
        }

    def get_best_template(self, task_type):
        """获取某类任务的最佳模板"""
        candidates = {k: v for k, v in self.templates.items() if task_type in k}
        if not candidates:
            return None
        return max(candidates.values(), key=lambda x: x["score"])

三种记忆的协同

graph TB
    Q[用户查询] --> C{查询分析}

    C -->|"做过类似的事吗?"| EP[情景记忆<br/>检索历史经验]
    C -->|"相关知识是什么?"| SM[语义记忆<br/>检索知识事实]
    C -->|"该怎么做?"| PM[程序记忆<br/>检索工作流]

    EP --> INT[记忆整合]
    SM --> INT
    PM --> INT

    INT --> LLM[LLM 推理]
    LLM --> ACT[行动/回答]

    ACT -->|记录经验| EP
    ACT -->|提取知识| SM
    ACT -->|更新流程| PM

实际应用示例

class IntegratedMemory:
    def __init__(self):
        self.episodic = EpisodicMemory(...)
        self.semantic = SemanticMemory()
        self.procedural = ProceduralMemory(...)

    def comprehensive_recall(self, query, task_type=None):
        """综合三种记忆进行回忆"""
        context = {}

        # 情景记忆:相关经验
        context["past_experiences"] = self.episodic.recall(query, n=3)

        # 语义记忆:相关知识
        entities = extract_entities(query)
        context["knowledge"] = []
        for entity in entities:
            context["knowledge"].extend(
                self.semantic.get_entity_knowledge(entity, depth=2)
            )

        # 程序记忆:适用的工作流
        if task_type:
            context["workflow"] = self.procedural.find_workflow(task_type)

        return context

记忆的更新与遗忘

知识冲突处理

当新信息与已有记忆冲突时:

def resolve_conflict(existing_fact, new_fact, llm):
    """处理知识冲突"""
    if new_fact["source"] == "user_explicit":
        # 用户明确陈述的优先级最高
        return new_fact

    if new_fact["timestamp"] > existing_fact["timestamp"]:
        # 更新的信息通常更可靠
        return new_fact

    # 让 LLM 判断
    resolution = llm.evaluate(
        f"已有知识: {existing_fact}\n新信息: {new_fact}\n哪个更可靠?为什么?"
    )
    return resolution

遗忘机制

并非所有记忆都需要永久保留:

  • 时间衰减:长时间未访问的记忆降低优先级
  • 重要性筛选:低重要性的记忆可以归档或删除
  • 容量管理:当存储接近上限时,清理最不重要的记忆

延伸阅读

  • 记忆流与反思机制 - Generative Agents 中的完整记忆架构
  • Tulving, E. (1972). "Episodic and semantic memory"
  • Park, J. S., et al. (2023). "Generative Agents: Interactive Simulacra of Human Behavior"
  • Shinn, N., et al. (2023). "Reflexion: Language Agents with Verbal Reinforcement Learning"

评论 #