cognee:仅用6行代码构建AI Agent记忆的知识引擎,15K星背后的工程哲学
前言:为什么AI Agent的记忆是个工程难题
大模型的上下文窗口再大,终究是有限的。当对话超过几轮之后,早期的关键信息就会被"挤出"上下文——这就是AI Agent领域著名的"第二天失忆"问题。
Claude-Mem为Claude Code解决的是项目级的持久记忆;GenericAgent、Evolver分别从极简约束和基因进化角度解决自我进化问题。但这些方案都有一个共同特点:强绑定。Claude-Mem绑定Claude Code,GenericAgent绑定自家框架,Evolver也有自己的生态。
那么问题来了:如果我想给任何一个Agent——无论它用什么模型、跑在什么框架上——都加上记忆能力,最小需要多少代码?
GitHub上15K星、增速稳定在200+星/天的开源项目cognee(原名agnee)给出了一个令人惊讶的答案:6行。
这就是本文要深度解析的核心:一个"记忆中间件"如何用极简接口解决了AI Agent记忆领域的最大痛点。
一、cognee是什么:从一个GitHub项目到一个知识引擎
1.1 项目基本信息
GitHub: https://github.com/topoteretes/cognee
Stars: 15,000+ (持续增长中)
语言: Python
许可证: Apache 2.0
定位: Knowledge Engine for AI Agent Memory in 6 lines of code
cognee由topoteretes团队开发,定位是"AI Agent的通用记忆知识引擎"。它不是为某一个特定的Agent框架设计的,而是一个与框架无关的抽象层——只要你的Agent能调用Python函数,就能用cognee管理记忆。
1.2 核心设计理念:解耦
cognee的设计哲学可以用一句话概括:让记忆成为可插拔的基础设施,而不是框架的一部分。
对比现有方案:
| 方案 | 绑定框架 | 记忆粒度 | 接入成本 |
|---|---|---|---|
| Claude-Mem | Claude Code专用 | 项目级 | 高(专有) |
| Hermes Agent Skills | Hermes专用 | 会话级+技能级 | 中(框架内) |
| GenericAgent | GenericAgent专用 | 基因/胶囊级 | 中 |
| Evolver GEP | EvoMap生态 | Prompt进化级 | 中 |
| cognee | 框架无关 | 任意粒度 | 极低(6行) |
cognee的本质是数据层抽象:它不关心你用什么Agent,只关心如何高效地存储、检索和压缩记忆数据。
1.3 为什么叫"知识引擎"而不是"记忆库"
"记忆"(memory)这个词在AI Agent语境下容易和"上下文窗口"混淆。cognee选择用"知识引擎"(Knowledge Engine)这个词,是因为它的核心能力不只是"记住",而是:
- 提取(Extract):从非结构化数据中抽取结构化知识
- 组织(Organize):将知识组织成可检索的图结构
- 检索(Retrieve):根据当前上下文高效召回相关记忆
- 压缩(Compress):在有限的上下文窗口内高效表达记忆
这四个能力构成一个完整的情报处理管线,和传统KV存储有本质区别。
二、6行代码背后的架构设计
2.1 最简接入示例
官方给出的6行核心示例:
import cognee
cognee.add(["John went to the store. Mary gave him an apple."])
cognee.add(["John gave the apple to Mary."])
cognee.llm_summarize("Summarize the interactions between John and Mary")
cognee.search("What did John do with the apple?")
这6行代码做了什么?让我们逐行拆解:
# 第1行:导入cognee包
import cognee
# 第2行:将第一条文本添加到记忆系统
cognee.add(["John went to the store. Mary gave him an apple."])
# 第3行:将第二条文本添加到记忆系统
cognee.add(["John gave the apple to Mary."])
# 第4行:让LLM对记忆进行摘要压缩
cognee.llm_summarize("Summarize the interactions between John and Mary")
# 第5行:在压缩后的记忆中检索答案
cognee.search("What did John do with the apple?")
看似简单,背后却是一个完整的数据管线。
2.2 内部架构分层
cognee的架构分为四层,每一层都可以独立配置和替换:
┌─────────────────────────────────────────┐
│ Application Layer │ ← 用户API (cognee.add / search / summarize)
├─────────────────────────────────────────┤
│ Cognitive Pipeline │ ← 认知处理管线
│ ┌──────────┐ ┌──────────┐ ┌─────────┐ │
│ │ Extraction│ │ Summariz.│ │ Rerank │ │
│ └──────────┘ └──────────┘ └─────────┘ │
├─────────────────────────────────────────┤
│ Storage Layer │ ← 存储抽象层
│ ┌──────────┐ ┌──────────┐ ┌─────────┐ │
│ │ VectorDB │ │ GraphDB │ │Document │ │
│ │ (可选) │ │ (可选) │ │ Store │ │
│ └──────────┘ └──────────┘ └─────────┘ │
├─────────────────────────────────────────┤
│ LLM Layer │ ← 大模型抽象层
│ 支持 OpenAI / Anthropic / Ollama / │
│ 本地模型 / 任何兼容接口 │
└─────────────────────────────────────────┘
关键设计:每一层都是可插拔的。你可以用Pinecone做向量存储,也可以用LanceDB本地存储;可以用GPT-4做摘要,也可以用本地Llama模型。cognee只是提供一个标准化的胶水层。
2.3 存储层:三元组与向量双轨制
cognee的记忆存储采用双轨制:
第一轨:知识图谱(Graph)
# 底层使用三元组存储
# 主语 - 谓词 - 宾语
("John", "went_to", "store")
("Mary", "gave", "apple")
("John", "gave_to", "Mary")
知识图谱的优势是可解释性和推理能力。你可以问"John给了Mary什么?",系统可以沿着图谱路径推理出答案。
第二轨:向量索引(Vector)
# 每条记忆同时生成向量嵌入
embedding(0.123, 0.456, 0.789, ...) # John went to the store...
embedding(0.234, 0.567, 0.890, ...) # John gave the apple to Mary...
向量索引的优势是语义相似度检索。你可以问"谁送了东西给Mary?",系统通过语义匹配找到相关记忆。
双轨融合:查询时,cognee会同时在图谱和向量索引中检索,然后融合排序返回最终结果。这是当前RAG领域的主流范式——图谱提供精确推理,向量提供语义泛化。
三、核心能力深度解析
3.1 认知处理管线(Cognitive Pipeline)
cognee的核心处理能力体现在它的认知管线中,包含以下关键步骤:
步骤1:文本提取(Text Extraction)
# cognee内部对输入文本进行分块处理
def extract(raw_text: str) -> list[TextChunk]:
# 1. 语义分块:按句子/段落边界切分,保持语义完整性
chunks = semantic_split(raw_text)
# 2. 实体识别:从文本中抽取实体
entities = extract_entities(chunks)
# 3. 关系抽取:从文本中抽取实体间关系
relations = extract_relations(chunks)
return chunks, entities, relations
步骤2:摘要压缩(Summarization)
这是cognee区别于简单KV存储的关键能力。当记忆量超过阈值时,cognee会调用LLM对记忆进行摘要:
async def llm_summarize(
texts: list[str],
question: str = None,
strategy: SummarizeStrategy = "map_reduce"
) -> str:
"""
map_reduce策略:
1. map阶段:每条记忆独立生成摘要
2. reduce阶段:所有摘要合并后再生成综合摘要
question参数:如果提供了问题,摘要会以回答该问题为导向
"""
if strategy == "map_reduce":
# 阶段1:每个chunk独立摘要
partial_summaries = []
for chunk in texts:
summary = await llm.agenerate(
f"Summarize concisely: {chunk}"
)
partial_summaries.append(summary)
# 阶段2:综合摘要
final_summary = await llm.agenerate(
f"Given these summaries, provide a coherent answer to: {question}\n"
+ "\n".join(partial_summaries)
)
return final_summary
为什么摘要重要? 假设你的Agent每天处理100个任务,每个任务产生500字的中间结果。一周后就有35K字的记忆——远超任何模型的上下文窗口。摘要将35K压缩到500字,但保留关键信息。
步骤3:检索重排(Retrieval & Rerank)
async def search(
query: str,
top_k: int = 5,
rerank: bool = True
) -> list[MemorySegment]:
# 1. 向量检索:找出语义相关的记忆
vector_results = await vector_index.search(query, top_k * 2)
# 2. 知识图谱检索:找出包含相同实体的记忆
graph_results = await graph_index.search(query, top_k * 2)
# 3. 融合排序(Reciprocal Rank Fusion)
fused = reciprocal_rank_fusion(
vector_results,
graph_results,
k=60 # RRF超参数
)
# 4. 可选:LLM重排(代价更高但更准确)
if rerank:
fused = await llm_rerank(query, fused, top_k)
return fused[:top_k]
Reciprocal Rank Fusion (RRF) 是一种无参数的排序融合算法:
def reciprocal_rank_fusion(results_list: list[list], k: int = 60) -> dict:
"""
对多个排序结果进行融合
k是平滑因子,通常设为60
"""
scores = defaultdict(float)
for results in results_list:
for rank, item in enumerate(results):
# RRF公式:1 / (k + rank)
scores[item] += 1 / (k + rank)
return sorted(scores.items(), key=lambda x: -x[1])
3.2 多模态记忆支持
cognee不只处理文本,还支持多种数据格式:
# 图片记忆
cognee.add([
Document(type="image", content=image_bytes, metadata={"source": "screenshot"}),
])
# 结构化数据
cognee.add([
Document(type="json", content={"user_id": 1, "action": "click"}),
])
# 音频转录
cognee.add([
Document(type="text", content=audio_transcript),
])
这种多模态支持使得cognee可以接入任何类型的Agent——不只是文本对话Agent,还有视觉Agent、语音Agent、甚至游戏AI。
四、与主流Agent框架的集成
4.1 通用集成模式
cognee的核心价值在于通用性。无论你用CrewAI、LangChain、AutoGen还是自研框架,cognee都可以作为记忆层接入:
# 通用集成模式
import cognee
class MemoryEnabledAgent:
def __init__(self, name: str):
self.name = name
cognee.cognify() # 初始化cognee系统
async def think(self, prompt: str) -> str:
# 1. 从记忆中检索相关上下文
relevant_memories = await cognee.search(
prompt,
top_k=5,
rerank=True
)
# 2. 将记忆注入prompt
context = self._format_memories(relevant_memories)
enriched_prompt = f"Context from memory:\n{context}\n\nTask: {prompt}"
# 3. 调用Agent核心(可以是任意模型)
response = await self.llm.agenerate(enriched_prompt)
# 4. 将交互结果存入记忆
await cognee.add([f"{self.name} responded: {response}"])
return response
def _format_memories(self, memories) -> str:
return "\n".join([
f"- {m.content} (relevance: {m.score:.2f})"
for m in memories
])
4.2 与CrewAI集成
from crewai import Agent
import cognee
# 初始化cognee
cognee.cognify()
# 定义带记忆的Agent
researcher = Agent(
role="Research Analyst",
goal="Conduct thorough research on given topics",
backstory="Expert research analyst with persistent memory",
verbose=True,
allow_delegation=False,
)
async def researcher_task(task: str):
# 检索相关记忆
memories = await cognee.search(f"research about: {task}", top_k=3)
# 将记忆作为背景知识注入
context = "\n".join([m.content for m in memories])
# 执行研究任务
result = await researcher.run(f"Previous research:\n{context}\n\n{task}")
# 存储新发现
await cognee.add([f"Research: {task} → {result}"])
return result
4.3 与LangChain集成
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
import cognee
# 配置cognee使用本地向量存储
cognee.cognify()
llm = ChatOpenAI(model="gpt-4")
class CogneeRetrievalChain:
def __init__(self, llm):
self.llm = llm
async def invoke(self, query: str) -> str:
# 1. 从cognee检索记忆
memories = await cognee.search(query, top_k=5)
# 2. 构建提示词
prompt = ChatPromptTemplate.from_messages([
("system", "You are a helpful assistant with access to memory."),
("user", f"Memory:\n{memories}\n\nQuestion: {query}")
])
# 3. 执行
return await (prompt | self.llm).ainvoke({})
五、生产环境部署实战
5.1 本地开发环境搭建
# 创建虚拟环境
python3 -m venv venv
source venv/bin/activate
# 安装cognee(基础版)
pip install cognee
# 安装可选依赖(根据存储后端选择)
pip install "cognee[pinecone]" # Pinecone向量存储
pip install "cognee[lancedb]" # 本地LanceDB(推荐开发)
pip install "cognee[postgres]" # PostgreSQL图存储
pip install "cognee[openai]" # OpenAI集成
pip install "cognee[anthropic]" # Anthropic集成
pip install "cognee[ollama]" # 本地Ollama集成
5.2 配置文件
# config.py
import cognee
cognee.config.set({
# 记忆存储配置
"storage.backend": "lancedb", # 开发环境用LanceDB
# "storage.backend": "pinecone", # 生产环境用Pinecone
"storage.lancedb.path": "./data/cognee_lancedb",
# 图存储配置
"graph.backend": "networkx", # 开发用NetworkX
# "graph.backend": "neo4j", # 生产用Neo4j
# LLM配置
"llm.provider": "openai",
"llm.model": "gpt-4",
"llm.api_key": "sk-...",
# 摘要策略
"summarize.threshold_tokens": 4000, # 超过4000token时触发摘要
"summarize.strategy": "map_reduce",
# 检索配置
"retrieve.top_k": 5,
"retrieve.enable_rerank": True,
})
5.3 Docker Compose一键部署
# docker-compose.yml
version: '3.8'
services:
cognee-api:
build: .
ports:
- "8000:8000"
environment:
- LLM_PROVIDER=openai
- LLM_API_KEY=${OPENAI_API_KEY}
- STORAGE_BACKEND=pinecone
- PINECONE_API_KEY=${PINECONE_API_KEY}
- PINECONE_INDEX=cognee-production
volumes:
- ./config.py:/app/config.py:ro
depends_on:
- redis
restart: unless-stopped
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis-data:/data
restart: unless-stopped
# 可选:Neo4j图数据库
neo4j:
image: neo4j:5-community
ports:
- "7474:7474"
- "7687:7687"
environment:
- NEO4J_AUTH=neo4j/password
volumes:
- neo4j-data:/data
restart: unless-stopped
volumes:
redis-data:
neo4j-data:
5.4 API服务封装
# app.py
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import Optional
import cognee
app = FastAPI(title="cognee Memory API")
class AddMemoryRequest(BaseModel):
content: str
metadata: Optional[dict] = None
class SearchRequest(BaseModel):
query: str
top_k: Optional[int] = 5
class SummarizeRequest(BaseModel):
topic: Optional[str] = None
strategy: Optional[str] = "map_reduce"
@app.on_event("startup")
async def startup():
cognee.cognify()
@app.post("/memory/add")
async def add_memory(req: AddMemoryRequest):
"""添加记忆"""
try:
await cognee.add([req.content])
return {"status": "ok", "content": req.content}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@app.post("/memory/search")
async def search_memory(req: SearchRequest):
"""检索记忆"""
try:
results = await cognee.search(req.query, top_k=req.top_k)
return {
"query": req.query,
"results": [
{
"content": r.content,
"score": r.score,
"metadata": r.metadata
}
for r in results
]
}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@app.post("/memory/summarize")
async def summarize_memory(req: SummarizeRequest):
"""摘要记忆"""
try:
summary = await cognee.llm_summarize(
question=req.topic,
strategy=req.strategy
)
return {"summary": summary}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
启动服务后,你就有了一个通用的记忆微服务——任何Agent都可以通过HTTP API接入记忆能力:
curl -X POST http://localhost:8000/memory/add \
-H "Content-Type: application/json" \
-d '{"content": "User asked about Python async/await syntax"}'
curl -X POST http://localhost:8000/memory/search \
-H "Content-Type: application/json" \
-d '{"query": "What Python topics has the user asked about?"}'
六、性能优化与最佳实践
6.1 记忆压缩策略
cognee支持多种压缩策略,适用于不同场景:
# 策略1:基于token阈值的自动摘要
cognee.config.set({
"summarize.threshold_tokens": 4000, # 超过4000token自动摘要
"summarize.strategy": "map_reduce"
})
# 策略2:基于时间的定期摘要
from datetime import datetime, timedelta
async def daily_compress():
"""每天凌晨2点执行一次记忆压缩"""
yesterday = datetime.now() - timedelta(days=1)
recent_memories = await cognee.search(
f"interactions after {yesterday.strftime('%Y-%m-%d')}",
top_k=100
)
await cognee.llm_summarize(
question="Summarize all key facts and decisions from the past day",
strategy="map_reduce"
)
# 策略3:基于重要性的选择性摘要
async def selective_compress():
"""只对"重要"记忆进行深度摘要"""
all_memories = await cognee.get_all()
for memory in all_memories:
# 用LLM判断重要性
importance = await llm.agenerate(
f"Rate the importance of this memory (1-10): {memory.content}"
)
if int(importance) >= 7:
# 重要记忆:生成详细摘要
memory.summary = await cognee.llm_summarize(
question=f"Provide detailed summary of: {memory.content}"
)
await memory.save()
else:
# 一般记忆:生成简短标签
memory.tag = await llm.agenerate(
f"Generate a one-word tag for: {memory.content}"
)
await memory.save()
6.2 存储后端选型
| 场景 | 推荐组合 | 说明 |
|---|---|---|
| 个人开发/小项目 | LanceDB + NetworkX | 完全本地,无需云服务 |
| 小团队(<100用户) | Qdrant + PostgreSQL | 开源,可私有部署 |
| 中型团队 | Pinecone + Neo4j | 托管服务,免运维 |
| 大型企业 | Weaviate + Neo4j + Redis | 高可用,支持多租户 |
# 多后端配置示例
cognee.config.set({
# 向量存储:Pinecone(语义检索)
"storage.backend": "pinecone",
"storage.pinecone.api_key": os.getenv("PINECONE_API_KEY"),
"storage.pinecone.environment": "us-east-1",
"storage.pinecone.index": "cognee-prod",
# 图存储:Neo4j(关系推理)
"graph.backend": "neo4j",
"graph.neo4j.uri": "bolt://localhost:7687",
"graph.neo4j.auth": ("neo4j", "password"),
# 缓存层:Redis(高频访问加速)
"cache.backend": "redis",
"cache.redis.url": "redis://localhost:6379",
"cache.ttl_seconds": 3600,
})
6.3 检索性能调优
# 检索管道优化
async def optimized_search(query: str):
# 第一层:快速向量检索(延迟<10ms)
fast_results = await vector_index.search(query, top_k=20)
# 第二层:图扩展(找出相关实体)
query_entities = extract_entities(query)
graph_results = await graph_index.search_by_entities(
query_entities,
depth=2
)
# 第三层:融合排序
fused = rrf_fusion(fast_results, graph_results, k=60)
# 第四层:可选LLM重排(延迟高但更准确)
if time_budget > 100ms:
fused = await llm_rerank(query, fused, top_k=5)
return fused[:5]
七、安全与隐私
7.1 数据隔离
cognee支持多租户数据隔离:
import cognee
# 每个用户独立的命名空间
async def add_memory_for_user(user_id: str, content: str):
cognee.config.set({
"storage.namespace": f"user_{user_id}",
"graph.namespace": f"user_{user_id}",
})
await cognee.add([content])
# 这条记忆只会出现在 user_id 的命名空间下
async def search_user_memory(user_id: str, query: str):
cognee.config.set({
"storage.namespace": f"user_{user_id}",
"graph.namespace": f"user_{user_id}",
})
return await cognee.search(query)
7.2 敏感信息过滤
from cognee.pipelines.filters import PIIFilter
# 配置PII过滤器
cognee.config.set({
"filters.enabled": True,
"filters.pii.strategies": {
"email": "mask", # 邮箱:脱敏
"phone": "remove", # 电话:删除
"ssn": "remove", # 身份证:删除
"credit_card": "remove", # 信用卡:删除
}
})
# 自动过滤后的记忆存储
await cognee.add([
"User john@example.com called 13800138000 about order #12345"
])
# 存储结果:"User [EMAIL] called [PHONE] about order #12345"
7.3 加密存储
cognee.config.set({
"storage.encryption.enabled": True,
"storage.encryption.key": os.getenv("ENCRYPTION_KEY"), # KMS管理
"storage.encryption.algorithm": "AES-256-GCM",
# 向量索引单独加密
"vector_index.encryption": True,
})
八、与其他记忆方案的对比总结
8.1 横向对比表
| 维度 | cognee | Claude-Mem | GenericAgent | Evolver |
|---|---|---|---|---|
| 接入代码量 | 6行 | ~50行 | ~30行 | ~40行 |
| 框架绑定 | 无 | Claude专用 | 自研框架 | EvoMap生态 |
| 存储架构 | 图谱+向量双轨 | 向量为主 | 图谱为主 | Prompt模板库 |
| 多模态 | 支持 | 文本 | 文本 | 文本 |
| 压缩策略 | LLM摘要+标签 | 向量压缩 | 基因突变 | 版本diff |
| 部署方式 | 任意 | Claude Code插件 | 自研 | 云服务 |
| 15K+Stars | ✅ | ❌ | ❌ | ❌ |
| LLM Agnostic | ✅ | ❌ | ❌ | ❌ |
8.2 cognee的核心差异化价值
1. 极低的接入成本
6行代码就能用,不需要理解复杂的框架概念。传统记忆系统的接入成本往往是"天"级别的学习和配置,cognee是"分钟"级别。
2. 真正的框架无关
Claude-Mem再好,也只能用Claude Code。cognee可以用在任何Agent里——这是一个本质区别。当你的团队使用多个不同框架的Agent时,cognee提供统一记忆层。
3. 可解释性
知识图谱存储使得cognee的记忆是可解释的。你可以问"这条记忆是什么时候产生的?谁触发的?关联了哪些实体?"——传统向量存储做不到这一点。
4. 生产级扩展性
从本地开发( LanceDB)到大型生产环境(Pinecone + Neo4j + Redis),cognee提供了一条平滑的升级路径。起步简单,随时可以扩展。
九、未来展望与局限性
9.1 当前局限性
1. 仍在快速迭代中
cognee目前15K星,但项目相对年轻,API稳定性不如老牌项目。生产环境使用前需要做好版本锁定和充分测试。
2. 图查询能力有限
当前版本的图检索主要依赖实体匹配,复杂的图推理(如多跳关系查询)能力还不够成熟。
3. 延迟问题
LLM摘要和重排的延迟较高,对实时性要求极高的场景(如高频交易)不太友好。
4. 分布式一致性
目前对多实例并发写入的一致性保障还不够完善,分布式部署需要额外注意。
9.2 路线图展望
根据GitHub的公开讨论和社区动态,cognee未来的方向可能包括:
- MCP协议集成:支持作为MCP Server提供记忆服务,与更多Agent框架原生集成
- 增量摘要:支持增量式摘要,而不是全量重写,降低延迟
- 多模态理解:对图片、音频内容做更深层的语义理解和记忆提取
- 主动记忆:Agent不再只是被动存储记忆,而是主动预测"未来可能需要什么"
9.3 适用场景判断
强烈推荐用cognee的场景:
- 需要跨框架统一记忆的异构Agent系统
- 快速原型开发,需要几天内搭建有记忆能力的Agent
- 对记忆可解释性有要求的生产系统
- 个人开发者,不愿意被特定框架绑定
不推荐用cognee的场景:
- 已经深度绑定Claude Code,只需要项目级记忆
- 超低延迟要求的实时系统
- 团队已经有成熟的记忆基础设施
结语:极简主义的一次胜利
cognee的成功不是偶然的。它代表了一种工程哲学:与其做复杂的功能,不如把简单的功能做到极致。
当Claude-Mem、GenericAgent、Evolver都在试图打造"完整的Agent解决方案"时,cognee选择只做一件事——记忆——并且把这件事的接入成本降到了最低。
6行代码的背后,是深思熟虑的抽象分层、灵活可插的存储架构,以及对"少即是多"原则的坚持。这种极简主义在AI Agent工具生态越来越臃肿的今天,显得格外珍贵。
如果你正在构建多Agent系统,或者需要给你的自研Agent加上记忆能力,cognee值得你花20分钟体验一下。
GitHub链接:https://github.com/topoteretes/cognee
本文参考资料:cognee GitHub官方文档、topoteretes团队技术博客、2026年4月GitHub Trending日报。