# 3.5 图记忆与知识图谱

前两节已经讨论了向量数据库与 Agent RAG 的能力边界，本节不再重复“为什么纯检索会失效”的一般论证，而是聚焦一个更具体的问题：当记忆需要表达实体、关系与时间演化时，为什么要引入图结构。**图记忆** 因而成为长期记忆的一种补充范式，常见实现包括带时间戳或有效期的知识图谱。

## 3.5.1 何时需要显式图结构

在 3.3/3.4 已说明纯向量检索难以处理时间冲突、实体指代与多跳关系后，这里只补充一个判断标准：如果系统需要稳定回答“谁在什么时候与谁发生了什么关系”，就应考虑把这些关系显式建模为图。

```mermaid
graph TD
    %% Agentic Design System
    classDef user fill:#fff7e6,stroke:#fa8c16,stroke-width:2px;
    classDef error fill:#fff1f0,stroke:#ff4d4f,stroke-width:2px;
    classDef system fill:#f0f0f0,stroke:#d9d9d9,stroke-width:2px,stroke-dasharray: 5 5;

    UserQuery(["用户：上周我提到的那个项目，进展如何？"])

    subgraph VectorSearch["向量检索的困境"]
        Problem1["无法理解 '上周' 的时间语义"]
        Problem2["无法追踪 '那个项目' 的指代关系"]
        Problem3["无法关联项目与进展的因果关系"]
        Result["返回语义相似但上下文无关的文档"]
    end

    UserQuery -.-> VectorSearch
    VectorSearch --- Problem1
    VectorSearch --- Problem2
    VectorSearch --- Problem3
    VectorSearch --> Result

    class UserQuery user;
    class Problem1,Problem2,Problem3,Result error;
```

图 3-5：向量搜索的局限性

图结构的价值不在于取代检索，而在于把“相关”转成“可遍历、可更新、可约束的关系”。

## 3.5.2 时序知识图谱核心概念

**时序知识图谱** 在传统知识图谱基础上增加了 **时间维度**，让智能体能够理解“什么时候发生了什么”。

### 基础结构

下图展示了一个简单的时序知识图谱示例，其中包含了人员、项目、事件等实体，以及带有时间范围的“负责”、“产出”等关系。这种结构清晰地表达了实体间随时间演化的动态关联。

```mermaid
graph LR
    %% Agentic Design System
    classDef user fill:#fff7e6,stroke:#fa8c16,stroke-width:2px;
    classDef memory fill:#fff0f6,stroke:#eb2f96,stroke-width:2px;

    subgraph TKG["时序知识图谱"]
        E1["张三<br/>人员"]
        E2["项目 Alpha<br/>项目"]
        E3["版本发布<br/>事件"]
        E4["项目 Beta<br/>项目"]

        E1 -->|"负责<br/>[过去一段时间]"| E2
        E1 -->|"负责<br/>[最近一段时间]"| E4
        E2 -->|"产出<br/>[某日期]"| E3
    end

    class E1 user;
    class E2,E3,E4 memory;
```

图 3-6：时序知识图谱结构示例

### 核心元素

时序知识图谱由三个核心元素组成：

* **实体**（Entity）表示人、项目、事件等节点；
* **关系**（Relationship）表示实体之间的连接，并带有时间有效期；
* **情节**（Episode）记录一次完整的交互或事件。

```python
from dataclasses import dataclass
from datetime import datetime
from typing import Optional, List

@dataclass
class Entity:
    """知识图谱中的实体节点"""
    id: str
    name: str
    entity_type: str  # Person, Project, Event, Concept...
    attributes: dict
    created_at: datetime
    updated_at: datetime

@dataclass
class Relationship:
    """实体之间的关系边"""
    id: str
    source_id: str
    target_id: str
    relation_type: str  # 负责, 参与, 产出, 依赖...
    attributes: dict
    valid_from: datetime  # 关系生效时间
    valid_to: Optional[datetime]  # 关系失效时间（None=当前有效）

@dataclass
class Episode:
    """一次交互或事件的完整记录（情节）"""
    id: str
    content: str
    entities: List[str]  # 涉及的实体ID列表
    relationships: List[str]  # 涉及的关系ID列表
    timestamp: datetime
    source: str  # conversation, document, observation...
```

## 3.5.3 混合记忆架构：图记忆 + RAG

图记忆通常不是孤立部署，而是与 RAG 组合使用：向量负责语义召回，图负责关系约束、时序约束和多跳推理。

```mermaid
graph TD
    %% Agentic Design System
    classDef user fill:#fff7e6,stroke:#fa8c16,stroke-width:2px;
    classDef memory fill:#fff0f6,stroke:#eb2f96,stroke-width:2px;
    classDef tool fill:#f6ffed,stroke:#52c41a,stroke-width:2px;
    classDef agent fill:#e6f7ff,stroke:#1890ff,stroke-width:2px;

    UserQuery(["用户查询"])

    subgraph Components["混合记忆架构"]
        GraphMem["图记忆<br/>关系"]
        VectorRAG["向量 RAG<br/>语义"]
        FullText["全文搜索<br/>关键词"]
    end

    Merge["结果融合<br/>重排序"]
    FinalContext(["最终上下文"])

    UserQuery --> GraphMem
    UserQuery --> VectorRAG
    UserQuery --> FullText

    GraphMem --> Merge
    VectorRAG --> Merge
    FullText --> Merge

    Merge --> FinalContext

    class UserQuery user;
    class GraphMem memory;
    class VectorRAG,FullText tool;
    class Merge agent;
    class FinalContext user;
```

图 3-7：图记忆与 RAG 混合架构

| 场景      | 推荐方案         |
| ------- | ------------ |
| 静态知识库问答 | 向量 RAG       |
| 长期用户交互  | 图记忆          |
| 多实体关系推理 | 图记忆          |
| 文档语义检索  | 向量 RAG       |
| 时间相关查询  | 图记忆          |
| 混合场景    | 图记忆 + 向量 RAG |

如果查询主要是文档相似度匹配，优先用向量检索；如果查询依赖实体一致性、时间线或多跳关系，再让图层参与重排或推理。

## 3.5.4 工程化落地路径

本节以工程视角归纳三类常见落地方式：图存储内核、知识抽取流水线，以及面向检索与推理的混合查询层。具体项目名与 API 细节可能随时间变化。

无论采用哪一种封装形态，底层通常都离不开“情节采集 → 实体关系抽取 → 图存储持久化 → 检索与推理接口”四个环节。

**架构概览**

```mermaid
graph TD
    %% Agentic Design System
    classDef agent fill:#e6f7ff,stroke:#1890ff,stroke-width:2px;
    classDef memory fill:#fff0f6,stroke:#eb2f96,stroke-width:2px;
    classDef tool fill:#f6ffed,stroke:#52c41a,stroke-width:2px;

    subgraph GraphStore["参考架构"]
        direction TB
        L1["情节处理层<br>处理用户对话/事件"]
        L2["知识提取层<br>利用 LLM 提取实体和关系"]
        L3["图存储层<br>持久化节点与边"]
        L4["检索层<br>混合检索（图遍历 + 向量相似度）"]

        L1 --> L2
        L2 --> L3
        L3 --> L4
    end

    class L1 agent;
    class L2 tool;
    class L3 memory;
    class L4 tool;
```

图 3-8：图记忆参考分层架构

这种分层架构实现了从非结构化文本到结构化图谱的自动流转：

1. **情节处理层**：作为系统入口，接收用户的对话、文档片段或观察到的事件。
2. **知识提取层**：利用 LLM 的语义理解能力，自动提取实体（Node）、关系（Edge）以及相关的时序元数据（Valid At）。
3. **图存储层**：将提取的三元组持久化到图数据库或图存储中，维护知识的演化历史。
4. **检索层**：提供混合检索能力，既能通过向量找到语义相关的节点，又能通过图遍历找到多跳关系节点。

**基础用法示例**

下例用伪代码展示典型工作流：初始化连接、写入情节、检索相关记忆。实现细节会因具体库而异，但接口形状通常相近。

```python
graph_memory = GraphMemory(
    graph_store=GraphStore(dsn="bolt://localhost:7687"),
    extractor=EntityRelationExtractor(model="claude-sonnet-4-6")
)

await graph_memory.add_episode(
    name="用户对话",
    content="用户：我刚加入了项目 Alpha 团队，负责后端开发。",
    timestamp=now(),
    source="conversation"
)

results = await graph_memory.search(query="用户在做什么项目？", k=5)
for item in results:
    print(item.fact)
    print(item.entities)
    print(item.valid_time)
```

**知识提取过程**

下面以通用流程为例：语言模型从对话中抽取实体与关系，再交由图存储进行持久化。

```python

# 输入对话

episode = "张三说他上周完成了项目 Alpha 的一次版本发布，现在开始负责项目 Beta。"

# LLM 提取的结构化知识

extracted = {
    "entities": [
        {"name": "张三", "type": "人员"},
        {"name": "项目 Alpha", "type": "项目"},
        {"name": "版本发布", "type": "事件"},
        {"name": "项目 Beta", "type": "项目"}
    ],
    "relationships": [
        {
            "source": "张三",
            "target": "项目 Alpha",
            "type": "完成",
            "valid_at": "上周"
        },
        {
            "source": "项目 Alpha",
            "target": "版本发布",
            "type": "发布",
            "valid_at": "上周"
        },
        {
            "source": "张三",
            "target": "项目 Beta",
            "type": "负责",
            "valid_from": "现在"
        }
    ]
}
```

### 方案二：记忆服务化

这类方案把“抽取、存储、索引、检索、评测”打包为独立服务，对应用侧暴露统一 API。优点是集成门槛低、便于运维与观测；代价是需要处理网络延迟、成本与数据治理。

```python
memory_service = MemoryServiceClient(endpoint="<ENDPOINT>", api_key="<API_KEY>")

await memory_service.add(
    user_id="user_123",
    session_id="session_456",
    messages=[
        {"role": "user", "content": "我想了解上次讨论的项目进展"},
        {"role": "assistant", "content": "我记得你负责的项目 Alpha 正在推进。"}
    ]
)

context = await memory_service.retrieve(user_id="user_123", query="项目进展", k=10)
```

**与向量检索的差异（概念层）**

图记忆类系统通常更擅长：实体一致性、时间线追踪、多跳关系；代价是：建模与抽取更复杂、存储与维护成本更高。具体准确率/延迟取决于数据、抽取提示词、存储后端与评测口径。

### 方案三：个性化画像记忆层

这类方案把“用户偏好、稳定事实、长期目标”抽取为可更新的画像，并与会话记忆解耦。常见策略包括去重、冲突消解与置信度更新。

```python
profile_memory = ProfileMemory()

profile_memory.add("我周末喜欢去爬山，但不喜欢去人多的地方。", user_id="alex_01")
related = profile_memory.search(user_id="alex_01", query="推荐个周末去处", k=5)
print(related)
```

## 3.5.5 实战：为智能体添加图记忆

以下示例展示了如何将图记忆集成到智能体中。核心流程是：检索相关记忆→构建增强上下文→生成回复→存储本次对话。这样智能体就能记住用户的历史信息并在后续对话中使用。

```python
from typing import List, Dict
class GraphMemoryAgent:
    """带有图记忆能力的智能体"""

    def __init__(self, llm, graph_memory):
        self.llm = llm
        self.memory = graph_memory

    async def chat(self, user_id: str, message: str) -> str:
        # 1. 检索相关记忆

        memories = await self.memory.search(query=message, k=10, filters={"user_id": user_id})

        # 2. 构建增强上下文

        memory_context = self._format_memories(memories)

        # 3. 生成回复

        response = await self.llm.generate(f"""
        你是一个有记忆的智能助手。

        用户历史记忆：
        {memory_context}

        用户问题：{message}

        基于历史记忆回答问题。如果记忆中没有相关信息，如实说明。
        """)

        # 4. 将本次对话存入记忆

        await self.memory.add_episode(
            name=f"对话-{user_id}",
            content=f"用户：{message}\n助手：{response}",
            timestamp=now(),
            source="conversation"
        )

        return response

    def _format_memories(self, memories: List) -> str:
        """格式化记忆为上下文"""
        if not memories:
            return "暂无相关历史记忆。"

        formatted = []
        for m in memories:
            formatted.append(
                f"- [{m.valid_time}] {m.fact}，相关实体：{', '.join(m.entities)}"
            )
        return "\n".join(formatted)
```

***

**下一节**: [3.6 上下文工程](/agentic_ai_guide/di-yi-bu-fen-dan-ti-zhi-neng-jia-gou/03_memory/3.6_context_engineering.md)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://yeasy.gitbook.io/agentic_ai_guide/di-yi-bu-fen-dan-ti-zhi-neng-jia-gou/03_memory/3.5_graph_memory.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
