在上一篇文章《百万 Token,却留不住一次经验:Agent 的记忆难题》中,我们讨论了 Agent 为什么需要记忆,也对 Cognee 的定位及核心能力进行了初步介绍。
但"将数据组织成 AI 可以使用的记忆",仍然是一个相对晦涩的描述。Cognee 目前支持普通文本、本地文件、S3 路径以及 HTTP/HTTPS URL 等多种输入形式。以 PDF 为例,将一篇文档交给 Cognee,待处理完成后,用户便可以围绕其中的内容进行提问。这个看似简单的过程,背后却包含了一条复杂的数据处理链路:PDF 首先需要被登记为一个数据对象,随后经过文本解析与切片,形成多个 Chunk;Embedding 模型会将相关内容转换成向量,大模型则会从中识别实体、概念及其关系。等到用户提出问题时,Cognee 还需要判断应该从原始文本、语义向量还是知识图中寻找证据,并将检索结果重新组织成模型能够使用的上下文。
那么,这些数据最终被存到了哪里?为什么同一段文字既要生成向量,又要进入知识图谱?召回阶段找到的是已经存储在数据库中的答案,还是用于生成答案的证据?当用户提交反馈、原始文档发生更新,或者某份数据被删除时,相关记忆又会发生怎样的变化?
要回答这些问题,首先需要理解 Cognee 为什么同时需要关系、向量和图三类存储,以及它们在记忆体系中分别承担什么职责。
在 Cognee 的官方架构中,一份完整的知识记忆由关系、向量和图三类存储共同承载,三者相辅相成:
关系存储负责管理数据的身份、来源和运行状态。比如一篇文档什么时候进入系统、属于哪个 Dataset、被切成了哪些 Chunk,以及这些内容由哪次 Pipeline 处理产生,都需要通过结构化记录进行管理。
向量存储负责保存文本、摘要、实体等对象的 Embedding。当用户提出问题时,Cognee 可以将问题转换成向量,再通过相似度计算,从大量知识对象中找到语义最接近的候选内容。
图存储则负责保存文档中的实体和关系。比如 Mars3、Bucket 等不再只是散落在文档中的词语,而会成为相互连接的知识对象。通过这些连接,系统可以进一步理解谁使用了什么、什么影响了什么,以及不同概念之间存在怎样的因果或依赖关系。
三类存储共同组成了 Cognee 的记忆体系,Cognee 并不强制三类数据必须放在同一种数据库中。

按照官方设计,关系、向量和图存储都可以根据实际需要选择不同的后端。例如,关系数据可以使用 SQLite 或 PostgreSQL,向量可以存入 LanceDB、PGVector 或其他向量数据库,知识图也可以交给独立的图数据库。不过,对于以原理分析和数据观察为目标的实验,PostgreSQL 是不二选择。它既是 Cognee 官方支持的关系数据库,也可以通过 pgvector 承载 Embedding 与向量检索,知识图的节点和关系同样以表的形式存储在 PostgreSQL 中。这意味着,一份文档产生的三类数据可以在同一个数据库中进行观察,关系记录、向量和图对象可以通过 ID 相互关联,我们也可以直接使用 SQL 观察 Remember、Recall、Improve 和 Forget 前后发生的变化。
本次实验基于 PostgreSQL 18.3 + Qwen text-embedding-v4 模型 + deepseek-v4-flash,Qwen text-embedding-v4 生成 Embedding,DeepSeek 负责内容理解、实体关系抽取和答案生成。为便于阅读,省略了环境变量、异常处理、日志和快照函数,并且由于实体和关系由大模型抽取,重新运行时数量可能存在差异。
remember 是 Cognee 面向使用者提供的高层入口。但一份文档进入 Cognee 后,并不会立刻成为可以检索和推理的知识。它首先要经过数据摄取,随后才能进入知识构建和增强阶段。
如果沿着底层流程继续拆解,可以将 remember 理解为 Add、Cognify 以及后续的知识增强。Add 处理的重点是数据本身:这是什么数据、来自哪里、属于哪个 Dataset、应当采用什么方式解析,以及当前处理到了什么状态。

本次实验以《AI时代,并行查询正从“扫得快”走向“算得快”》为例,并将其归入名为 mars3_bucket 的独立 Dataset。核心调用只有一行:
import cognee
DATASET = "mars3_bucket"
PDF_PATH = './AI 时代,并行查询正从"扫得快"走向"算得快".pdf'
await cognee.add(PDF_PATH, dataset_name=DATASET)
Cognee 接收到这份 PDF 后,首先保存原始文件,随后调用 pypdf_loader 提取其中的文本,并将解析结果保存为后续流程可以读取的文件。与此同时,关系数据库中会建立三个重要对象:
Dataset:数据的逻辑容器,本次实验中对应 mars3_bucket;
Data:代表进入 Cognee 的具体数据对象,本次对应这篇 PDF;
dataset_data:负责记录这份 Data 属于哪个 Dataset。
从数据库中看到的链路大致如下:

data 表中的记录显示,原始输入类型为 application/pdf,解析后的数据类型为 text/plain;original_data_location 指向原 PDF,raw_data_location 指向抽取后的文本。pipeline_status 则记录 Add 和 Cognify 是否完成。
cognee_article_db=# select mime_type,original_mime_type,loader_engine,token_count from data;
-[ RECORD 1 ]------+----------------
mime_type | text/plain
original_mime_type | application/pdf
loader_engine | pypdf_loader
token_count |5838
同时,在 Add 完成后查询了几个关键对象:
SELECT 'data' AS object, count(*) AS rows FROM data
UNION ALL SELECT 'dataset_data', count(*) FROM dataset_data
UNION ALL SELECT 'graph_node', count(*) FROM graph_node
UNION ALL SELECT 'graph_edge', count(*) FROM graph_edge
ORDER BY object;
object | rows
--------------+-----
data | 1
dataset_data | 1
graph_edge | 0
graph_node | 0
在本文使用的 PostgreSQL 存储路径中,知识对象和关系分别落在 graph_node 与 graph_edge 表中,相关图查询通过 SQL JOIN 和递归 CTE 完成,graph_node 是知识图中的通用节点表,其中既有文档、Chunk 和摘要等过程对象,也有从原文中抽取出的实体及实体类型。graph_edge 则保存这些节点之间的连接关系。
这说明现阶段 Cognee 已经知道这份数据是谁、来自哪里、属于哪里,也完成了文本解析,但图中还没有任何节点和关系。此时被记住的主要是数据身份和解析结果,并不是文档中关于 MARS3、Bucket、并行查询和数据重分布的具体知识。回到 Cognee 的 Brain 页面,也可以看到 mars3_bucket 以及刚刚进入系统的 PDF:

真正将连续文本组织成知识,则需要进入下一步 cognify:
await cognee.cognify(datasets=[DATASET])
执行结束之后,结果发生变化:
SELECT'data'AS object, count(*) ASrowsFROM data
UNIONALLSELECT'dataset_data', count(*) FROM dataset_data
UNIONALLSELECT'graph_node', count(*) FROM graph_node
UNIONALLSELECT'graph_edge', count(*) FROM graph_edge
ORDERBY object;
object |rows
--------------+------
data | 1
dataset_data | 1
graph_edge | 157
graph_node | 66
(4rows)
Data 没有重复增加,但数据库中出现了 66 个图节点和 157 条关系,其中包括 1 个 TextDocument、7 个 DocumentChunk、7 个 TextSummary、41 个 Entity 和 10 个 EntityType。
这组变化直接反映了两个阶段的职责差异:Add 负责让数据进入记忆系统,Cognify 则开始把连续文本整理成可以检索和关联的知识对象。
如果直接用整篇文档生成 Embedding,检索粒度会很粗糙,当用户询问 nbuckets 或 Redistribute Motion 时,检索只能将整篇文档取回来。内容虽然相关,粒度却过于粗糙,模型还要重新从几千 Token 中寻找答案。
因此,Cognee 首先将解析文本组织成一个 TextDocument,再由 Chunker 将其拆成若干 DocumentChunk。Chunk 既是后续模型处理的基本单位,也是 Recall 时可以独立返回的原始证据。

本次实验使用的 PDF 共 7 页,解析后形成了 7 个 Chunk。它们分别覆盖文章背景、普通并行扫描、Mars3 Bucket 原理、执行计划和参数说明等内容,平均长度约为 836 个字符。值得注意的是,此处的 "7 页" 和 "7 个 Chunk" 只是数量上的巧合,Chunk 的边界由解析文本、切片策略和长度设置共同决定。它既要控制在模型能够处理的长度内,也要尽量保持一段技术解释的上下文。比如,普通并行扫描为什么可能引入 Redistribute Motion,前后涉及 Worker 如何取得数据、相同 Key 如何分散以及局部聚合后为什么还要重新分布。若这段逻辑从中间被切开,后续抽取到的关系就可能只剩结果,没有原因。
不过,Chunk 仍然主要保留原文。为了让这些内容可以被概括、计算和关联,Cognee 还会围绕每个 Chunk 继续生成其他知识对象。
为了观察这个过程,我们从 7 个 Chunk 中选取了编号 2。它包含 780 个字符,其中一段原文是:
MARS3 Bucket 不是简单的分桶功能,也不是一个面向语法层的逻辑切分手段。其核心目标,是让并行扫描之后,数据仍然保持良好的本地性,让更多计算继续在本地完成……当多个进程同时扫描时,不再只是"谁先抢到哪一页就扫哪一页",而是"每个 Worker 扫描自己所负责的一组 Bucket"。
这段原文进入 Cognify 后,首先生成了一条 TextSummary。它概括了 Mars3 Bucket 如何在 Data Node 内组织数据、如何为 Worker 分配 Bucket,以及 Worker 如何参与 Bucket 扫描等。
一个值得注意的现象是:原始 Chunk 为 780 个字符,模型生成的 Summary 却有 1032 个字符,而且采用了英文表达。由此也可以看出,TextSummary 更准确的含义是"另一种语义表达",它并不保证一定比原文短,输出语言和精炼程度也会受到模型、提示词及生成参数影响。
随后,大模型开始从这段文本中识别实体。编号 2 的 Chunk 通过 contains 关联了 5 个实体,分别是 data node、mars3 bucket、master、t_sales 和 worker。
WITH chunk_2 AS (
SELECT payload::jsonb->>'id'AS id
FROM "DocumentChunk_text"
WHERE (payload::jsonb->>'chunk_index')::int=2
)
SELECT target.name
FROM graph_edge edge
JOIN chunk_2
ON edge.source_id = chunk_2.id
JOIN graph_node target
ON target.id = edge.target_id
WHERE edge.relationship_name ='contains'
AND target.type ='Entity'
ORDERBY target.name;
name
--------------
data node
mars3 bucket
master
t_sales
worker
(5rows)
这些内容不再只是原文中的词语,而是变成了带有 ID、类型、描述和来源的知识对象。Cognee 通过 contains 记录实体来自哪个 Chunk,再通过 is_a 将实体连接到相应类型。
在识别实体的同时,大模型还会抽取实体之间的关系。本次实验中,编号 2 的 Chunk 形成了多条完整的三元组:

这种"起点实体—关系—终点实体"的表达形式,就是 Cognee 中经常提到的 Triplet,即三元组。相比单独列出关系名称,完整三元组保留了关系方向和两端对象,一段自然语言由此被转换成可以查询和遍历的知识结构。

SQL 查询能够精确列出节点和关系,但当关系逐渐增多时,表格并不容易呈现它们如何连接。将同一批对象放到 Mindmap 中,以 mars3 bucket 为中心展开,文档中的技术逻辑会直观许多。


在这张局部关系图中,MARS3 Bucket 不再只是文档中出现的一个术语。它与 nbuckets、worker、redistribute motion、local aggregation 等对象建立了明确连接:nbuckets 描述其配置方式,Worker 承担 Bucket 扫描,Bucket 组织方式保留数据分布语义,并进一步减少 Redistribute Motion。
这就是知识图与关键词列表的差别。关键词只能说明某些词在文档中出现过;知识图还保存了它们之间的关系、方向和语义。
当然,这些三元组来自模型对原文的理解。它们是结构化抽取结果,仍然需要回到原文核验。Cognee 可以保存关系、方向和文字解释,但模型能否正确理解业务语义,仍然受到原文质量、提示词和模型能力的影响。
Chunk、Summary、实体和关系形成后,Cognee 还会为其中需要检索的字段生成 Embedding。本次测试使用的是 Qwen text-embedding-v4,所有向量均为 1024 维。数据库中最终形成了六类向量记录:
文档名称:TextDocument_name
Chunk 原文:DocumentChunk_text
Chunk 摘要:TextSummary_text
实体名称:Entity_name
实体类型:EntityType_name
关系语义:EdgeType_relationship_name
数据库中的实际数量如下:
SELECT 'DocumentChunk_text' AS collection, count(*) AS rows
FROM "DocumentChunk_text"
UNION ALL SELECT 'TextSummary_text', count(*) FROM "TextSummary_text"
UNION ALL SELECT 'Entity_name', count(*) FROM "Entity_name"
UNION ALL SELECT 'EntityType_name', count(*) FROM "EntityType_name"
UNION ALL SELECT 'EdgeType_relationship_name', count(*) FROM "EdgeType_relationship_name"
UNION ALL SELECT 'TextDocument_name', count(*) FROM "TextDocument_name"
ORDER BY collection;
collection | rows
----------------------------+------
DocumentChunk_text | 7
EdgeType_relationship_name | 157
EntityType_name | 10
Entity_name | 41
TextDocument_name | 1
TextSummary_text | 7
(6 rows)
这些名称已经体现了 Cognee 的组织方式:
DocumentChunk_text 表示对 Chunk 的原文生成向量
Entity_name 表示对实体名称生成向量
TextSummary_text 则对应模型生成的摘要
每条向量记录都通过对象 ID 与原始知识对象保持对应。编号 2 的 Chunk 在向量表中仍然使用相同的 ID;它对应的 Summary 也保存了来源 Chunk 的信息。这样,即使 Recall 先通过摘要向量找到相关内容,系统仍然可以继续返回原始片段。
关系同样会形成向量。本次实验中,EdgeType_relationship_name 保存了 157 条记录,与当前知识图中的 157 条边一致。这里索引的不只是 scanned_by、assigns_buckets_to、is_a 等关系标签,还包含关系两端及其文字解释,为自然语言问题寻找相关图连接提供语义入口。
向量擅长回答的是哪些 Chunk、摘要、实体或关系在语义上与当前问题接近?但它无法独立说明 Bucket 与 Worker 的连接方向,也无法完整表达 c1 如何映射到 Bucket。具体的对象、方向和关系,仍然需要知识图保存。
除了节点名称、类型和属性,Cognee 还会在图节点与图关系中保存 Dataset、Data 和 Cognify Run 等来源信息。
这些字段平时并不显眼,却是整套记忆机制的重要基础。借助它们,系统可以继续回答:
某个实体来自哪份数据?
某条关系由哪次 Cognify 生成?
某个 Chunk 属于哪个 Dataset?
删除一份文档时,哪些知识对象会受到影响?
如果图中只有实体和关系,却没有来源信息,知识就会逐渐变成无法解释的孤立结论。Improve 很难判断应该增强什么,Forget 也无法确定一份数据究竟留下了哪些影响。
回到编号 2 的 Chunk,经过 Cognify 后,它在数据库中留下的已经不再只是一段文本:

Chunk 保存原始证据,Summary 提供另一种语义表达,向量帮助自然语言问题找到候选,知识图记录对象之间的连接,来源信息则把这些结果重新系回原始数据和处理过程。
这也是 Cognify 在整条记忆链路中的作用:它把 Add 阶段得到的连续文本,整理成一组可以追溯、检索和关联的知识对象,为接下来的 Recall 提供基础。

而当越来越多的实体、类型和关系进入知识图后,下一个问题也随之出现:Cognee 如何概括这张图中存在哪些知识类型,又如何描述这些类型之间的关系?这便涉及 Memory Schema。
经过 Cognify,这篇文档形成了 41 个实体和 10 种 EntityType。当前识别出的类型包括 benchmark、column、concept、executionplannode、operation、parameter、person、system、table 和 technology。
Memory Schema 可以看作当前实体类型及其关系的观察视图。它没有在关系、向量和图之外增加第四类存储,而是帮助我们快速查看 Cognee 从文档中识别出了哪些知识类型,以及这些类型之间形成了怎样的连接。
通过这张视图,我们可以快速观察 Cognee 如何理解这篇文档,也可以发现类型划分是否合理、实体是否重复,以及某些关系是否偏离原文。

Memory Schema

Bucket 实体关系
至此,一篇 PDF 已经拥有原文、摘要、向量、实体、类型和关系。但数据库中保存了这些对象,并不意味着 Agent 在提问时一定能够找到正确内容。接下来,记忆才真正进入使用阶段。
为了观察 Recall 的实际过程,我们继续围绕 Mars3 Bucket 提出问题:
Mars3 Bucket 如何减少 Redistribute Motion,并让下游算子进行本地计算?
本次实验分别使用了基于 Chunk 的 RAG 和基于知识图的检索。
from cognee.modules.search.types.SearchType import SearchType
question = "MARS3 Bucket 如何减少 Redistribute Motion,并让下游算子进行本地计算?"
vector_result = await cognee.search(
query_text=question,
query_type=SearchType.RAG_COMPLETION,
datasets=[DATASET],
top_k=4,
verbose=True,
)
graph_result = await cognee.search(
query_text=question,
query_type=SearchType.GRAPH_COMPLETION,
datasets=[DATASET],
top_k=5,
wide_search_top_k=30,
verbose=True,
)
基于 Chunk 的路径比较直接。问题首先由 Embedding 模型转换成向量,再到 DocumentChunk_text 中寻找语义距离较近的原文片段。取回的内容涉及 Bucket 划分、Worker 扫描方式、Redistribute Motion 和本地聚合,随后交给大模型组织答案。
图检索同样先从向量查找入口,但候选范围不再局限于 Chunk。Cognee 会从文档、Chunk、摘要、实体、实体类型和关系等不同向量集合中寻找候选,再将候选 ID 映射回 graph_node 和 graph_edge,组合成带有方向的三元组上下文。

Chunk 路径取回了 4 个原文片段,图检索返回了 5 组图上下文。两条路径都能够回答问题,但提供证据的方式有所区别:
Chunk 中保留了相对完整的执行计划和技术描述,适合核对原文、参数和限定条件
图检索进一步串联了 Key 到 Bucket 的映射、Worker 分工,以及本地计算与结果汇总之间的联系。
两条路径的处理成本也不同。本次单次调用中,Chunk 检索耗时 ~1.83 秒,图检索 ~3.16 秒。图检索需要访问多类向量对象,并将候选重新映射到节点和边,因此链路更长。当然,模型服务、网络延迟、候选数量和上下文长度都会影响最终耗时,这组数据只用于记录本轮实验过程,不作为性能结论。
检索策略仍然取决于问题。查参数、原文和具体描述时,Chunk 通常可以满足需求;当需要理解多个实体之间的连接时,知识图更有价值。
更重要的是,两次 Recall 前后,Data、图节点、图关系和六类知识向量的数量均未发生变化。Recall 使用的是已经形成的知识,并没有向长期记忆中写入新的内容。
Recall 解决了如何使用过去的知识,但 Agent 在工作过程中还会持续产生新的信息。
例如,一次数据库排障结束后,用户确认了故障原因,也认可了最终处理方案。如果这段经历只停留在当前 Session 中,下次遇到类似问题时,Agent 仍然需要从头开始。Improve 关注的,正是这些交互如何进入长期记忆。
此次我向 Cognee 提出了下面的问题:
在 YMatrix 中,对 MARS3 表执行按 c1 分组聚合时,为什么 nbuckets=1 不一定最快?请依据文章说明。
Cognee 返回答案后,我们提交了 5 分的反馈,并对该 Session 执行 Improve。核心代码流程如下:
from cognee.api.v1.session.session import add_feedback, get_session
result = await cognee.search(
query_text=QUESTION,
query_type=SearchType.GRAPH_COMPLETION,
datasets=[DATASET],
top_k=5,
wide_search_top_k=30,
session_id=SESSION_ID,
verbose=True,
)
entries = await get_session(SESSION_ID)
await add_feedback(
session_id=SESSION_ID,
qa_id=entries[0].qa_id,
feedback_text="回答与文档内容一致,明确解释了进程协同开销和局部计算的关系。",
feedback_score=5,
)
await cognee.improve(
dataset=DATASET,
session_ids=[SESSION_ID],
feedback_alpha=0.2,
)
从处理链路看,Improve 没有直接修改原 PDF,也没有重新训练 DeepSeek。它首先读取 Session 中的问题、召回上下文和最终答案,再将 Question 与 Answer 组织成一份新的 Session 文本,随后重新执行 Add 和 Cognify。


这意味着,一次问答要进入长期记忆,仍然要经历与普通文档相似的处理过程。它需要获得数据身份,被切成可以检索的片段,再形成摘要、实体、关系和向量。
本轮 Improve 新增了 1 份 Data、1 个 TextDocument、1 个 Chunk 和 1 个 Summary。图节点从 66 增至 80,增加了 14 个;图关系从 157 增至 197,增加了 40 条。
新增的 14 个节点包括 1 个 TextDocument、1 个 DocumentChunk、1 个 TextSummary、6 个 Entity、4 个 EntityType 和 1 个 NodeSet。对应的实体向量从 41 增至 47,实体类型向量从 10 增至 14,关系向量从 157 增至 197。
沿着来源信息继续检查,可以看到这份 Session 最终支持了 18 个节点和 42 条边。其中,14 个节点和 40 条边只由该 Session 支持;另外 4 个节点和 2 条边同时受到原 PDF 等其他来源支持。
这说明 Improve 并不是把一次问答完全独立地追加到图中。遇到已有对象时,Cognee 可以复用原有节点,并为它们增加新的来源。来源信息决定了后续 Forget 时,哪些对象可以删除,哪些对象仍然需要保留。

于是,同一个实体可以同时由产品文档和实际问答支持。
这一步体现了长期记忆与简单数据追加之间的区别。如果每一次交互都重新创建一套实体,随着 Agent 持续运行,知识图中很快就会充满重复对象。复用已有实体,并记录新的来源,才能让后续经验真正接入已经形成的知识。
来源信息在这里承担了关键作用。系统既要知道一个实体是否存在,也要知道它由哪些数据支持。只有这样,后续删除其中一份来源时,才能判断这个实体应当保留还是移除。
完成 Improve 后,我们使用相近问题再次执行 Recall。Chunk 检索共返回 5 个结果,新生成的 Session Chunk 排在第一位;图检索返回 8 个 Triplet,其中 5 条关系带有本次 Session 的来源。
其中出现了一条新的关系:nbuckets=1 -- may_not_be_fastest --> count(*),这说明 Improve 形成的内容已经参与后续召回,而不只是增加了几条无法使用的数据库记录。
对同一个 Session 再执行一次 Improve,Data、图节点、图关系和向量记录均没有继续增加,本轮重复调用表现为幂等。
能够形成记忆之后,还要解决如何遗忘。文档可能过期,用户可能要求删除历史会话,一次排障结论也可能后来被证明有误。对于已经形成 Chunk、摘要、实体、关系和向量的数据,只删除原始文件显然不够。因此 Forget 需要沿着数据来源继续处理:

为了观察这一过程,我们只删除 Improve 产生的 Session Data,原 PDF 及其知识继续保留。
result = await cognee.forget(
data_id=SESSION_DATA_ID,
dataset=DATASET,
)
Forget 完成后,Data 从 2 条回到 1 条,Dataset 关联从 2 条回到 1 条;图节点从 80 回落到 66,图关系从 197 回落到 157。Improve 新增的 1 个 Document、1 个 Chunk、1 个 Summary、14 个独占节点和 40 条独占关系随之消失。
Session Data、Dataset 关联以及节点和关系中的 Session 来源引用均已清零。第二次对同一条 Data 执行 Forget,数据库内容没有继续变化,本轮重复删除表现为幂等。

再次 Recall 时,Chunk 检索结果全部来自原 PDF;图检索返回的节点和关系也不再包含 Session 来源。这说明 Session 已经形成的长期知识得到撤销,没有继续参与后续召回。
现在再回头看最初的那篇 PDF,它经历的并不是一次简单的文件导入。Add 为数据建立身份,Cognify 将连续文本组织成 Chunk、摘要、实体、关系和向量,Recall 从这些表示中寻找当前问题所需的证据,Improve 将新的交互接入已有知识,Forget 则沿着来源撤销不再需要的长期记忆。
一份文档保存在数据库中,只能说明数据没有丢失。它被切分、关联和召回,回答才有证据;它能够追溯来源、接纳新经验并处理删除,才具备长期使用的基础。
这次实验也说明,Agent Memory 远不只是模型上下文之外增加一个向量库。它同时涉及结构化状态、语义向量、图关系、来源追踪和生命周期管理。
这些知识表示并不是彼此孤立的。新增一份数据时,Chunk、实体、关系和向量需要一起建立;删除一份数据时,也需要沿着来源处理它留下的知识。对于 Agent Memory 来说,真正的难点不是保存更多内容,而是让这些内容在后续任务中可用,并在数据变化时仍然可追溯、可管理。
理解 Cognee 的关键,也不仅是记住 Add、Cognify、Recall、Improve 和 Forget 几个操作。更重要的是看清:一份内容如何形成多种知识表示,这些表示如何共同参与检索,又如何在持续更新和删除过程中保持一致。
下一篇,我们将回到 Cognee 与 CittaBase 的结合。关系、向量和图为什么需要协同?当这些数据交给同一套数据库能力承载后,部署、检索和生命周期管理会发生什么变化?这将是第三篇继续讨论的问题。