拆解2.8万Star开源项目Cognee:如何基于知识图谱做RAG和Agent记忆

项目:topoteretes/cognee

Stars:27.1k | 语言:Python 85% | 许可:Apache-2.0

Cognee是面向智能体的开源AI记忆平台。它用一套可本地部署的知识图谱引擎,为AI智能体提供跨会话的持久长期记忆。项目实现路径本质还是基于RAG的那套体系。

记忆数据分两层摄入:
知识记忆把文档、PDF、代码库等领域的知识,通过cognee.add()+cognify()构建成知识图谱
会话记忆把对话片段、用户偏好、交互模式等会话内容通过cognee.remember()存入系统,并且支持session_id维度的缓存

项目自身提供的Claude Code插件是典型的应用场景:记录prompts、工具调用轨迹和助手回复,在会话结束时自动同步到知识图谱。

拆解2.8万Star开源项目Cognee:如何基于知识图谱做RAG和Agent记忆

* *

部署使用

Cognee的部署门槛很低:只要接入一个LLM的API key就能跑,因为它所有的默认数据库都是类似SQLite这种单文件数据库。

最小依赖

uv pip install cognee
只需要一个环境变量:

LLMAPIKEY="youropenaiapi_key"
默认的嵌入式存储,不需要额外服务:

| 数据库 | 职责 | 存储内容 |
| — | — | — |
| SQLite | 关系数据 | 元数据、用户、数据集、权限 |
| LanceDB | 向量存储 | embedding向量 |
| Ladybug(兼容旧Kuzu路径) | 图数据库 | 知识图谱(实体、关系、三元组) |
补充一个细节:项目文档里仍然把本地图库入口写成Kuzudb,但源码配置里的默认GRAPHDATABASEPROVIDER已经是ladybug,只是继续兼容旧的kuzu命名和历史数据路径。

Ladybug是Kuzu的直接继承者和活跃的开源分支。Kuzu原开发团队的核心成员被苹果公司收购后,原项目被归档停止维护,开源社区接管并启动了Ladybug,负责修复安全漏洞并持续推进。社区称它为“图数据库界的DuckDB”

生产环境

生产环境部署建议直接切到PostgreSQL,而且也是一个数据库搞定图、向量、会话、元数据存储,部署也很方便:

pip install "cognee[postgres]"# .envDBPROVIDER=postgresVECTORDBPROVIDER=pgvectorGRAPHDATABASEPROVIDER=postgresCACHEBACKEND=postgresDBHOST=localhostDBPORT=5432DBUSERNAME=cogneeDBPASSWORD=cogneeDBNAME=cogneedb
项目的CI benchmark说明是:同样跑在PostgreSQL上时,搜索速度比“图+向量分离”的方案快约10%,但是没说召回准确率相关的数据。

可换后端数据库
图数据库:可以切到postgres、neo4j、neptune
向量数据库:可以切到pgvector、chromadb、qdrant、weaviate、milvus
会话缓存:支持sqlite、postgres、redis、fs、tapes,默认是sqlite

支持 Docker 部署

基础 API 服务docker compose up# 加前端 UIdocker compose –profile ui up# 加 MCP 服务docker compose –profile mcp up# 全套docker compose –profile ui –profile mcp –profile postgres up

资源参考:API服务建议4 CPU / 8GB内存,MCP服务建议2 CPU / 4GB内存。

LLM 兼容性

Cognee基于litellm接主流模型提供商。切换时改provider和key就够:

LLMPROVIDER="anthropic"LLMAPIKEY="youranthropic_key"
litellm是一个Python SDK,以OpenAI兼容格式接入100多个LLM API,内置成本追踪和负载均衡。
* *

怎么接入使用

Cognee的接入方式:

Python API:精确管控使用add → cognify → search。直接走Agent记忆层,用remember → recall

import cognee# graph pipelineawait cognee.add("document.pdf")await cognee.cognify()results = await cognee.search("What is…")# memory APIawait cognee.remember("User prefers detailed explanations.", sessionid="chat1")results = await cognee.recall("What does the user prefer?", sessionid="chat1")
CLI命令行:适合快速验证和脚本集成

cognee-cli remember "Cognee turns documents into AI memory."cognee-cli recall "What does Cognee do?"cognee-cli forget –all
项目自带本地Web UI:cognee-cli -ui。另外这个命令背后的MCP server是跑在Docker容器里的,所以本机要能跑的起来Docker。

Claude Code插件:直接给Claude Code加持久记忆

claude plugin marketplace add topoteretes/cognee-integrationsclaude plugin install cognee-memory@cognee
插件会监听Claude Code的生命周期:SessionStart→UserPromptSubmit→PostToolUse→Stop→PreCompact→SessionEnd,自动注入上下文并在session结束时回刷知识图谱。

运行模式分本地和远端:本地模式默认会在http://localhost:8011自举本地Cognee API;远端/云端模式则改用COGNEEBASEURL+COGNEEAPIKEY直连远端实例。

MCP Server:标准MCP协议接入,支持HTTP / SSE / stdio三种传输模式。

docker run -e TRANSPORT_MODE=http –env-file ./.env -p 8000:8000 cognee/cognee-mcp:main
多语言客户端:除Python外,官方还提供了Rust (cargo add cognee)和TypeScript (npm install @cognee/cognee-ts)客户端。

OpenClaw插件:npm install @cognee/cognee-openclaw

Docker容器:两种方式

方式一:从源码构建docker compose up                    # API 服务docker compose –profile ui up       # + 前端界面(localhost:3000)docker compose –profile mcp up      # + MCP 服务(localhost:8001)docker compose –profile postgres up # + PostgreSQLdocker compose –profile neo4j up    # + Neo4j# 方式二:拉取预构建镜像docker run –env-file ./.env -p 8000:8000 cognee/cognee:main

Cognee Cloud:官方提供的全托管服务,通过SDK直连

import cogneeawait cognee.serve(url="https://your-instance.cognee.ai", apikey="ck…")
其他云平台:Modal(Serverless)、Railway(PaaS)、Fly.io(边缘部署)、Render(托管Postgres),每个都有对应的部署脚本或一键部署方式。
* *

以上是安装部署使用的介绍,下面是主要实现部分的技术拆解,目录:
数据摄入
分片策略
检索/召回
核心算法:Brute Force Triplet Search(暴力三元组搜索)
GraphCompletionRetriever:默认检索器
存储架构
与传统RAG的差异
基准测试Benchmark
* *

数据摄入

Cognee的数据处理有两层API:
memory APIremember()、recall()、forget()、improve(), Agent记忆链路主路径
graph pipeline APIadd()、cognify()、search(),精确控制数据摄入、抽取、检索链路

如果只是Agent记忆系统,从官方quickstart看其实主要走remember/recall方法

如果看具体技术实现路径,就要看add/cognify/search这些方法实现。remember()内部实现(如果不带会话ID参数)也是走add()+cognify()。

执行主链是这样:

await cognee.add("document.pdf")   # 添加数据await cognee.cognify()             # 构建知识图谱results = await cognee.search("What is…")
add()负责接收、处理数据:
默认loader加载器覆盖PDF、CSV、JSON和普通文本,代码文件也是按文本导入
docx/pptx/xlsx这类Office文档,通常要额外装cognee[docling]或cognee[docs]可选依赖。
cognify()是核心处理步骤,把原始数据构建成知识图谱:
classify_documents把原始Data item归类成Document
extractchunksfrom_documents切chunk
extractgraphand_summarize并行做chunk级图抽取和摘要
adddatapoints把节点、边和embedding落到图/向量库
extractdltfk_edges如果是DLT数据,再补外键边

如果启用temporal_cognify=True,这条链会换成事件/时间戳抽取的时间线流水线(temporal pipeline)。

remember() 先决定走哪条摄入路径

remember()是统一的记忆注入入口,根据参数走不同的模式:

无sessionid(永久记忆):自动运行add()+cognify();如果不手动关闭selfimprovement,还会继续跑一次improve()做enrichment增强

有sessionid(会话记忆):先写会话缓存(session cache);只要selfimprovement=True,后台就会异步improve(dataset=…, sessionids=[sessionid]),把session的Q&A和trace桥接回永久图,同时把feedback作用到图元素权重上
这里的self_improvement不是一个抽象的“自动优化”开关,而是remember()默认附带的第二段处理:对永久记忆路径,它会在cognify()之后继续跑improve(),给图补三元组嵌入(triplet embedding)和索引;对会话记忆路径,它会把session里的内容异步桥接回永久知识图谱,让后续检索不只停留在临时cache。

会话内容是有时效性的,系统对此的处理方式如下:

会话缓存本身有独立生命周期,默认TTL是7天;但improve(sessionids=…)把会话桥接到永久图时,当前实现主要是把整段Q&A序列化后写进usersessionsfromcache这个node set,并不会把cache的TTL语义原样带到图里。

这意味着,Cognee现在对“这是不是时效性记忆”的区分,更多还是靠来源分层和上层策略,也就是需要外部业务系统处理,项目不包含永久图内建的过期治理:
usersessionsfrom_cache把原始会话回灌进图,适合保留可复用问答、偏好、反馈线索,也方便后续追溯
session_learnings先经过会话上下文的置信度和有害内容门控(harmful gating),再提炼成经验(lesson),更适合长期沉淀的“提炼后记忆”
所以“哪些值得永久化、哪些只是临时上下文、是否要在session end时同步、是否要过滤路径/任务状态/一次性噪音”这些,更多还是你在外层决定。

remember()示例

永久记忆:进入知识图谱await cognee.remember("Einstein was born in Ulm.")# 会话记忆:先写缓存,后台同步到图await cognee.remember("User prefers detailed explanations.", sessionid="chat1")

拆解2.8万Star开源项目Cognee:如何基于知识图谱做RAG和Agent记忆

remember()还支持结构化记忆条目:
QAEntry问答对(问题、上下文、答案、反馈)
TraceEntryAgent追踪步骤(函数调用、状态、输入输出)
FeedbackEntry用户反馈(关联到某个QA)
SkillRunEntry技能运行记录

这些条目类型让Agent记住的不只是文本,还有问答、工具调用轨迹、反馈和技能运行结果。

分片策略

分片链路执行是在永久记忆路径进入cognify()之后,如果参数带sessionid,首次写入不会走分片逻辑,但是如果selfimprovement开启,需要把会话写入永久图,这时候也可能发生分片(把会话内容序列化后分片)。

Cognee默认的分片处理器是TextChunker。它的执行顺序是一条四层流水线:

async def TextChunker.read(document):    buffer = []    buffersize = 0    for textblock in document.gettext():        for chunkdata in chunkbyparagraph(            textblock,            maxchunksize=maxchunksize,            batchparagraphs=True,        ):            if buffersize + chunkdata["chunksize"]                 buffer.append(chunkdata)                buffersize += chunkdata["chunksize"]            elif not buffer:                # 单个 chunk 本身就够大,直接产出                yield DocumentChunk(text=chunkdata["text"], …)            else:                # 把前面攒下来的段落块拼成一个正式 DocumentChunk                yield DocumentChunk(text=" ".join(chunk["text"] for chunk in buffer), …)                buffer = [chunkdata]                buffersize = chunkdata["chunksize"]def chunkbyparagraph(text, maxchunksize):    # 按 sentence 流累积,超上限时切一块    for paragraphid, sentence, sentencesize, endtype in chunkbysentence(        text,        maximumsize=maxchunksize,    ):        accumulatesentencesuntillimit()def chunkbysentence(text, maximumsize):    # 用 embedding tokenizer 计 token;句子超上限就切成 sentencecut    for word, wordtype in chunkbyword(text):        accumulatewordsuntilsentenceendorsizelimit()def chunkbyword(text):    # 先切最底层 token:单词 / 空格 / 句末符 / 段落换行    yield wordorsentenceboundary
它尽量保住词边界,再保句子边界,再拼成段落块,最后由TextChunker聚合成真正写入图谱的DocumentChunk。
DocumentChunk字段包含:text、chunksize、chunkindex、documentid、documentname和contains。

其中contains初始是空列表,后面extractgraphfrom_data()方法会把抽出来的chunk图谱和实体回填进去(基于LLM提取),于是形成一条chunk → contains → 节点/边的映射链,后面的检索召回也是可以通过这个字段回查DocumentChunk。

Cognee还另外提供了TextChunkerWithOverlap(带重叠)、LangchainChunker(递归字符分割)、CsvChunker(CSV专用)等分片器,但分片不是Cognee的核心,用默认的就差不多了。

检索/召回

Cognee的检索层支持17种模式,但主要检索路径有三条:
CHUNKS最轻,纯向量检索,直接返回文档块
RAG_COMPLETION中间态,用文档块做传统RAG,再交给LLM生成答案
GRAPH_COMPLETION最重,也是Cognee的主要能力,先从图里找相关三元组,再让LLM组织回答

如果显式设置GRAPH_COMPLETION模式,走的是知识图谱三元组,不是完整的文档块,而且这条路径的前提是数据摄入的时候跑过cognify()。

拆解2.8万Star开源项目Cognee:如何基于知识图谱做RAG和Agent记忆

最简:纯向量检索,不碰知识图谱await cognee.add("docs/")results = await cognee.recall("query", querytype=SearchType.CHUNKS)# 中等:传统 RAG,文档块 + LLMresults = await cognee.recall("query", querytype=SearchType.RAGCOMPLETION)# 完整:知识图谱推理await cognee.cognify()results = await cognee.recall("query", querytype=SearchType.GRAPH_COMPLETION)

这里的GRAPH_COMPLETION依赖的是图里沉淀后的语义信息,而不是默认回灌完整原始chunk;但如果节点或者边里本身带了chunk相关文本,它也会一起被序列化进LLM上下文。这让它更擅长回答关系、归因、跨文档连接类问题,但在原文细节保真上不如RAG路线。

项目的search()和recall()方法的默认行为并不一致:
search()的默认querytype是GRAPHCOMPLETION
Python SDK的recall()如果不显式传querytype,默认autoroute=True,会先走一层规则路由
HTTP/v1/recall仍使用GRAPHCOMPLETION默认值;只有显式传searchtype=null才会自动路由

这个“自动路由”本质上还是关键词/模式匹配 + 权重打分:

if querytype is not None:    # 你显式指定了类型,就按你指定的跑    # autoroute 这时只做 override 记录,不改最终执行类型    use(querytype)elif autoroute:    scores = {}    for pattern, searchtype, weight in RULES:        if pattern.matches(querytext) and not negatednearby(querytext):            scores[searchtype] += weight    if not scores or max(scores.values()) 2.0:        use(GRAPHCOMPLETION)   # 没命中明确规则,回退默认图检索    else:        use(argmax(scores))     # 分数最高的 SearchType 胜出else:    use(GRAPH_COMPLETION)
路由规则大致分这几类:
Cypher语法MATCH … RETURN …这类原生图查询,直接路由到CYPHER
代码规则问题coding rules、code review、lint、refactor,再加上def / async / import / .py这类编程语境,路由到CODING_RULES
精确短语检索整句被引号包起来,或者出现exact / verbatim / literal,路由到CHUNKS_LEXICAL
摘要类问题summarize、overview、tldr、key takeaways,路由到GRAPHSUMMARYCOMPLETION
解释/推理类问题why、explain、step by step、chain of thought,路由到GRAPHCOMPLETIONCOT
关系/连接类问题related to、connected to、path between、degree of separation,路由到GRAPHCOMPLETIONCONTEXT_EXTENSION
时间类问题when、timeline、between 1910 and 1920、1915这种带明显时间信号的查询,路由到TEMPORAL

一个小细节:规则命中前会看一下附近有没有not / no / never / without这种否定词,避免把“not related to”也误判成关系查询。

autoroute目前不会把普通问答自动分到RAGCOMPLETION、CHUNKS或HYBRIDCOMPLETION。大多数没有明确特征的自然语言问题,最后会回落到GRAPHCOMPLETION,它不是基于深层语义理解的检索策略选择器。

项目支持17种SearchType,但常使用的,还是“纯chunk检索”“传统RAG”“图谱推理”这三档,再加一个recall()的自动路由。

当前SearchType枚举一共17个:

| 类型 | 用途 | 是否用LLM |
| — | — | — |
| GRAPH_COMPLETION | 图推理 + LLM回答 | ✅ |
| RAG_COMPLETION | 传统RAG,纯文档块 | ✅ |
| CHUNKS | 纯向量相似度,返回文本块 | ❌ |
| CHUNKS_LEXICAL | BM25词法匹配 | ❌ |
| SUMMARIES | 预生成摘要 | ❌ |
| CYPHER | 直接写Cypher查询图数据库 | ❌ |
| FEELING_LUCKY | 自动选最佳策略 | ✅ |
| AGENTIC_COMPLETION | 带skill/tool的Agent检索 | ✅ |
| HYBRID_COMPLETION | 混合检索(图+向量) | ✅ |
| TRIPLET_COMPLETION | 三元组直接回答 | ✅ |
| GRAPHCOMPLETIONCOT | 图推理 + 链式思考 | ✅ |
| GRAPHCOMPLETIONDECOMPOSITION | 图推理 + 问题分解 | ✅ |
| GRAPHSUMMARYCOMPLETION | 图推理 + 摘要 | ✅ |
| GRAPHCOMPLETIONCONTEXT_EXTENSION | 图推理 + 上下文扩展 | ✅ |
| NATURAL_LANGUAGE | 自然语言转图查询 | ✅ |
| TEMPORAL | 时序数据检索 | ✅ |
| CODING_RULES | 编码规则检索 | ✅ |

recall()还有一层“从哪些记忆源取”的开关。它支持scope=graph/session/trace/graphcontext/sessioncontext/all/auto。默认其实就是auto:有session_id时先查session,没有时直接查graph;如果你显式扩scope参数,它还可以同时带上trace、session context和回刷到cache的graph context。

results = await cognee.recall(    "What does the user prefer?",    sessionid="chat1",    scope=["session", "graph"],)
* *

核心算法:Brute Force Triplet Search(暴力三元组搜索)

系统默认的GRAPH_COMPLETION走的是一套多阶段流水线:查询 → 向量搜索 → 图投影 → 距离映射 → 三元组打分 → LLM生成。

向量搜索定位种子节点

查询文本先经过embedding,然后在多个collection中并行做相似度检索。这里也不是把5个collection硬编码死了:GraphCompletionRetriever会扫描所有DataPoint子类里metadata.index_fields指定的字段,动态拼出可检索集合。默认文档 / 记忆 场景里,最核心的通常是这几个:

collections = [    "Entityname",              # 实体名称    "TextSummarytext",         # 文本摘要    "EntityTypename",          # 实体类型    "DocumentChunktext",       # 文档块    "EdgeTyperelationshipname" # 关系类型]
这一步的作用是先做一轮宽搜:从多个collection里拿到相关节点候选,同时也拿到边类型相关的向量分数,供后面映射到图上。注意:真正拿来做图投影种子的主要是节点ID,不是边类型ID。单query默认会用widesearchtop_k=100截断这批候选,再做后面的子图投影,batch查询则直接走全图投影。

图投影——两种模式

拿到种子节点ID后,从图数据库中拉出相关子图。两种模式通过neighborhood_depth参数切换:

ID过滤投影(单query默认):先用种子节点ID过滤,从图数据库拉相关子图。如果图数据库支持getidfilteredgraphdata,会优先走ID过滤;如果adapter不支持,或者过滤结果为空,才回退到拉全图。

邻域投影:以种子节点为起点,沿边扩展k跳,只拉局部邻域。这种方式在大图上更高效,避免拉出不相关的远端节点。
上面这套“种子节点 -> 子图投影”的描述主要对应单query路径。batch查询时不会从宽搜结果里抽种子节点ID,而是直接投影全图,再分别按query计算triplet排名。

nodesdata, edgesdata = await adapter.getneighborhood(    nodeids=seednodeids,    depth=depth,           # 跳数,如 1、2、3    edgetypes=edgetypes  # 可选:只沿特定关系类型走)
邻域模式还有一个细节:对扩展发现的新节点,会补一轮ID过滤的向量搜索,让这些节点也有向量分数,参与后续排序。

距离映射

图投影完成后,图中的节点和边还没有"相关性分数"。距离映射就是把向量搜索的结果"写"到图元素上。

具体过程:

1.向量搜索返回一批结果,每个结果有id和score(cosine距离,范围0~2,越小越相关)

2.遍历这些结果,在图中找到对应的节点或边

3.把score写到该节点/边的vector_distance字段

节点距离映射for result in nodedistances:    node = graph.getnode(result.id)  # 在图中找到这个节点    node.vectordistance = result.score  # 写入向量分数# 边距离映射for result in edgedistances:    edges = graph.edgesbydistancekey[result.id]  # 通过 edgetypeid 找到匹配的边    for edge in edges:        edge.vectordistance = result.score

未命中的元素怎么办?

图中有些节点/边没有被向量搜索命中(不在topk结果里),它们的vectordistance会被设为默认惩罚值tripletdistancepenalty(默认6.5)。

这个惩罚值有讲究:正常的cosine距离范围是0~2,惩罚值6.5远大于这个范围。这意味着:
被向量命中的元素:距离0~2,排序靠前
未被命中的元素:距离6.5,排序靠后

这样就实现了"向量搜索快速缩小范围,图结构补充关系"的效果。

三元组打分

每个三元组(Node1 – Edge – Node2)的分数计算方式:

def score(edge):    importances = []    for element in [node1, node2, edge]:        distance = element.vectordistance[queryindex]        importanceweight = element.importanceweight  # 取不到时回退到 0.5        feedbackweight = element.feedbackweight      # 用户反馈累积        # 核心公式:重要性权重调整距离        adjusteddistance = (2 – importanceweight) * distance        # 混合反馈权重        final = blend(adjusteddistance, feedbackweight)        importances.append(final)    return sum(importances)  # 三个元素的距离求和
排序逻辑:距离越小越相关。用heapq.nsmallest(k, edges, key=score)取top_k个三元组。

importanceweight的含义:权重越高,调整后的距离越小,该元素越容易被选中。不过这里也要说清楚:源码默认投影的importanceweight主要是节点属性;edge在很多场景下拿不到这个字段,会回退到默认值0.5。所以它更准确地说是“让重要节点更容易被选中”,而不是“所有关系边都会同等享受这个加权”。

反馈权重混合

Cognee的反馈机制类似点赞:用户使用中对回答答案给出1-5分评分,好答案的来源节点权重会提升,坏答案的来源节点权重会压低。

反馈来源:Session中的QAEntry记录了feedbackscore(1-5分)和usedgraphelementids(这次问答使用了哪些图节点/边)。

识别条件:
feedback_score必须是1-5的整数
usedgraphelementids必须包含nodeids或edge_ids(知道哪些节点/边被用过)
还没有被处理过(避免重复更新)

权重更新公式(指数移动平均):

def streamupdateweight(previousweight, feedbackscore, alpha):    # feedbackscore 1-5 映射到 0-1    normalizedrating = (feedbackscore – 1) / 4    # EMA 更新:alpha 控制学习率    updated = previousweight + alpha * (normalizedrating – previousweight)    return max(0.0, min(1.0, updated))  # 裁剪到 [0, 1]
检索时的影响:
默认情况下反馈权重不参与排序。feedbackinfluence默认值是0.0,也就是默认检索不混入反馈权重;只有你显式把feedbackinfluence调大,或者改了全局配置,下面这套blending才会参与排序。

feedback_influence(0~1)控制反馈对排序的影响程度:

def effectivedistance(distance, feedbackweight):    # 只对有效距离(0~2范围内的 cosine 距离)做混合    if distance >= tripletdistancepenalty or distance 0 or distance > 2:        return distance  # 惩罚值不参与混合    normalizeddistance = distance / 2.0    blended = (1 – feedbackinfluence) * normalizeddistance               + feedbackinfluence * (1 – feedbackweight)    return blended * 2.0
feedback_weight越高(接近1),混合后的距离越小,该元素排名越靠前。

关键点:
反馈是显式的(用户主动给1-5分)
关联是精确的(只更新实际用到的节点/边)
更新是渐进的(EMA,不会剧烈波动)
默认是关闭混合影响的;要显式把feedback_influence打开,反馈才会进入召回排序

完整流程

拆解2.8万Star开源项目Cognee:如何基于知识图谱做RAG和Agent记忆

* *

GraphCompletionRetriever:默认检索器

GraphCompletionRetriever位于cognee/modules/retrieval/graphcompletionretriever.py,是图检索的默认实现。

完整流水线

class GraphCompletionRetriever(BaseRetriever):    async def getcompletion(self, query):        # 1. 准备(含 session 上下文)        turnpreparation = await self.preparesessionturnforretrieval(query)        # 2. 检索三元组        retrievedobjects = await self.getretrievedobjects(query)        # 3. 三元组 → 文本上下文        context = await self.getcontextfromobjects(query, retrievedobjects)        # 4. LLM 生成回答        completion = await self.getcompletionfromcontext(query, context)        return completion

关键特性

全局上下文索引:设置includeglobalcontext_index=True后,会在triplet context之前先拼一段全局前言。它由root summary和top summaries组成,本质上还是对TextSummary的向量检索。

参考文献:设置include_references=True后,Cognee不会直接把“这次命中的图元素”拿来当引用,而是会拿生成后的回答再反查chunk index,补一段证据块(Evidence block)。

批量查询:支持query_batch参数,一次处理多个查询,内部共享图投影,减少重复计算。

Session 缓存机制

Cognee的会话缓存是一整套session级结构化数据,也就是问答对(question/context/answer)记录:

await cognee.remember("User prefers detailed explanations.", sessionid="chat1")results = await cognee.recall("What does the user prefer?", sessionid="chat1")
这个缓存和Claude Code / Codex保存的会话transcript不是一类东西。后两者主要是为了恢复和继续agent会话;Cognee的session cache更像一个可检索的会话记忆层,会先把结构化会话内容缓存下来参与召回,并可在self_improvement开启时进一步同步到永久知识图。

这个“结构化会话内容”首先就是一轮QA。正常的session回答链路会把每一轮存成question / context / answer这样的结构化问答对,后续session recall取回的也是这些QA记录;但如果你是直接调用remember(…, sessionid="chat1")往会话里塞一段内容,首次写入的则不是完整问答,而更像一条question=""、context=""、answer=text的会话记忆记录。除了QA之外,session cache里还可以带agent trace、sessioncontext和graphcontext。

Session缓存的工作方式,用伪代码写大致是这样:

async def remember(data, *, sessionid=None, selfimprovement=True):    if sessionid is None:        # 永久记忆路径:add -> cognify -> improve        return await addandcognify(data)    # 会话记忆路径:先写 session cache    await addtosessioncache(        sessionid=sessionid,        qa={            # 正常 session turn 通常是完整 question/context/answer            # 直接 remember(sessionid=…) 注入时,往往更像 answer=text            "question": "",            "context": "",            "answer": data,        },    )    # 默认后台再跑 improve,把 session 内容桥接回永久图    if selfimprovement:        spawnbackgroundtask(            improve(dataset="maindataset", sessionids=[sessionid])        )async def recall(query, *, sessionid=None, datasets=None, querytype=None, scope="auto"):    if scope == "auto":        if sessionid and not datasets and querytype is None:            # 默认会话模式:先查 session,再决定要不要掉回 graph            sessionhits = await searchsessionqa(query, sessionid=sessionid)            if sessionhits:                return sessionhits  # short-circuit            return await searchgraph(query)        if sessionid and (datasets or querytype is not None):            # 显式带 dataset / querytype 时,session 和 graph 一起参与            return merge(                await searchsessionqa(query, sessionid=sessionid),                await searchgraph(query, datasets=datasets, querytype=querytype),            )        return await searchgraph(query)    # 显式 scope 时,还可以把 trace / graphcontext / sessioncontext 一起带上    return await recallfromexplicitsources(        query,        sessionid=session_id,        scope=scope,    )
remember(sessionid=…)负责把内容先放进会话缓存;recall(sessionid=…)则在默认模式下优先查session QA,只有没命中时才继续掉回图检索。只有你显式扩scope,或者同时给了datasets / query_type,它才不再是简单的“session first, graph fallback”。
* *

存储架构

Cognee 1.0的一个特点:把所有存储层统一到PostgreSQL。

传统方案                    Cognee 方案─────────────────────────────────────────Neo4j (图)        →        Cognee 的 Postgres graph backendRedis (会话)      →        SQL session cache向量数据库         →        pgvector关系数据库         →        PostgreSQL
本地开发模式更轻量:SQLite + LanceDB + Ladybug/Kuzu兼容图库,零外部依赖,全部是单文件数据库,会话缓存默认也是SQLite。
* *

与传统 RAG 的差异

Cognee的整体架构本质上仍然在RAG范式里:文档摄入、分块、索引、召回、LLM生成,这些骨架都没变。它在传统chunk-RAG之外叠了一层图检索和会话记忆机制,重点增强的是Agent场景下的关系召回、会话连续性和知识沉淀。

下面这张对比表可以理解为“传统chunk-RAG”和“Cognee的完整memory + graph路线”的对比,因为实际上Cognee不是所有检索都会自动走图谱三元组:

| 维度 | 传统RAG | Cognee(记忆增强RAG) |
| — | — | — |
| 索引结构 | 文档块 + 向量 | 文档块 + 向量 + 知识图谱 + session cache |
| 主要检索单元 | 文档块(chunk) | 可切换:chunk、图三元组、session QA |
| 生成上下文 | 相似文档块拼接 | 取决于模式:文档块、图三元组文本化结果、会话上下文 |
| 多跳关系召回 | 通常靠多次检索或上层编排 | 图路径更容易显式表示关系链,但回答仍要靠LLM组织 |
| 会话记忆 | 通常靠外部对话层补 | 内建Session缓存,并可桥接到永久图 |
| 反馈机制 | 通常无内建反馈回路 | 有显式feedbackweight / feedbackinfluence,但默认不是强开启 |
| 知识持久化 | 多为一次性建索引后查询 | 支持追加摄入、session桥接和部分权重更新,但不等于默认在线持续学习 |

核心区别在于:
图结构让检索不只盯着chunk相似度,还能显式利用实体、边和关系路径
记忆层Session缓存、session → graph桥接、可选反馈权重,让系统多了一层“会话记忆”能力
多路检索既能当纯chunk-RAG用,也能切到图检索或混合检索,而不是只有一条图谱路径
* *

基准测试 Benchmark

Cognee当前公开了两组比较有代表性的benchmark结果:一组是长上下文记忆场景下的BEAM,另一组是多跳问答场景下的HotPotQA子集评测。

BEAM:长上下文记忆

BEAM测试系统在长对话中追踪信息变化的能力,比传统的needle-in-a-haystack更贴近Agent记忆场景。

| 设置 | Cognee | 前任SOTA | RAG基线 |
| — | — | — | — |
| 100K tokens | 0.79(按题路由可到 >0.8) | 0.735 | ~0.33 |
| 10M tokens | 0.67 | 0.641 | ~0.33 |

Cognee自称在100K设定下超过了前任SOTA,在10M设定下大致打平。而且提醒:这组数字更适合看趋势,不太适合脱离具体方法细节单独拿出来下结论。

HotPotQA:多跳问答

项目在一个24题的HotPotQA子集上做了repeated-run评估,并把整组实验概括成45个评估轮次(evaluation cycles)。

参与对比的系统包括:
Mem0基于OpenAI的记忆QA系统
GraphitiLangChain + Neo4j知识图谱QA
LightRAGFalkor的GraphRAG-SDK

评估指标包括DeepEval Correctness、EM、F1和Human-like Correctness。

Cognee在DeepEval Correctness(0.846)、EM(0.687)、F1(0.841)三项上领先;但Human-like Correctness最高的是LightRAG(0.955),Cognee是0.925,并不是所有指标都第一。

这也说明了Cognee的成绩和具体检索配置关系很大。单看benchmarksummarycognee.json,GRAPHCOMPLETIONCOT是表现最好的一档,其次是GRAPHCOMPLETIONCONTEXTEXTENSION,最后才是基础GRAPHCOMPLETION。如果换回默认基础配置,Cognee Graph Completion的分数会明显低一档:Correctness 0.743、EM 0.596、F1 0.724、Human-like Correctness 0.805。

拆解2.8万Star开源项目Cognee:如何基于知识图谱做RAG和Agent记忆

拆解2.8万Star开源项目Cognee:如何基于知识图谱做RAG和Agent记忆

* *

最后

如果你也在构建Agent记忆系统这样的项目,Cognee的很多实现细节是个很好的参考,甚至可以直接集成到项目中。

如果你在构建RAG知识库项目,Cognee也值得参考,它本身就是一个RAG系统。当成RAG知识库使用也是可以的,而且部署也很简单。

拆解LangChain刚开源的OpenWiki:如何落地个人Wiki知识库

RAG知识库的核心组件:PDF/OCR解析 看这些开源项目就够了

企业落地新闻资讯智能化改造

AI时代,企业最大的升级,不是降本增效,而是重构运行方式

2026-7-18 13:00:37

RAG技术前沿技术新闻资讯

企业AI三件套:语义层、动力层、决策层——少一件都做不出AI原生

2026-7-18 14:53:23

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
购物车
优惠劵
搜索