Cognee开源项目实战:为AI智能体构建长期记忆系统
在构建智能体(Agent)应用时,一个核心的痛点日益凸显:如何让AI记住与用户的每一次对话、每一次交互,并在后续的交流中灵活调用这些“记忆”,从而实现真正连贯、个性化的智能体验?传统的会话管理往往局限于单次对话的上下文窗口,一旦对话结束,AI便“失忆”了。今天,我们将深入探讨一个由OpenAI创始人Sam Altman投资、旨在解决这一难题的开源项目—— Cognee 。本文将带你从零开始,全面解析Cognee的核心概念、架构设计,并通过一个完整的实战案例,手把手教你如何为你的AI应用装上“长期记忆”。
1. 背景与核心概念:为什么AI需要记忆?
在深入Cognee之前,我们首先要理解“AI记忆”的必要性。当前主流的大语言模型(LLM)应用,无论是基于OpenAI API还是开源模型,其交互模式大多是“无状态”的。这意味着:
- 上下文限制 :模型只能处理有限长度的提示词(Prompt),超出部分会被截断。
- 会话隔离 :每次对话都是全新的开始,模型无法记住用户的历史偏好、习惯或之前讨论的细节。
- 个性化缺失 :无法基于用户的长期行为数据提供定制化的回复或服务。
这严重限制了AI助手、客服机器人、个性化推荐系统等应用的深度和用户体验。 Cognee 应运而生,它将自己定位为一个 “AI记忆层” 或“长期记忆系统”。其核心目标是:为任何AI应用(尤其是基于LLM的智能体)提供一个统一、可扩展的框架,用于存储、检索和管理与实体(如用户、文档、会话)相关的长期记忆。
简单来说,Cognee就像是为你的AI大脑外接了一个“海马体”(大脑中负责记忆的区域)。它不替代LLM的推理能力,而是为其提供持久化的“经验”数据,让AI能够进行基于上下文的、连贯的、个性化的思考与回应。
2. Cognee 核心架构与工作原理
Cognee并非一个简单的键值存储数据库。它是一个精心设计的系统,其架构融合了现代AI工程的最佳实践。理解其架构是有效使用它的关键。
2.1 核心组件
Cognee的架构主要包含以下几个层次:
-
记忆存储(Memory Storage) :
- 功能 :持久化保存记忆数据。Cognee支持多种后端,包括本地文件系统、矢量数据库(如Chroma, Weaviate, Pinecone)、关系型数据库等。
- 类比 :相当于计算机的硬盘,负责数据的长期存放。
-
记忆处理与索引(Memory Processing & Indexing) :
- 功能 :这是Cognee的“智能”所在。它使用嵌入模型(Embedding Model)将文本记忆转换为高维向量(Vector),并建立向量索引。同时,它可能对记忆进行结构化处理(如提取实体、关系、摘要)。
- 类比 :相当于图书馆的编目系统,不仅藏书,还为每本书建立索引卡片(向量),方便快速查找。
-
记忆检索(Memory Retrieval) :
- 功能 :根据当前查询(用户问题或上下文),从记忆库中找出最相关的记忆片段。通常采用 语义搜索 (基于向量相似度)和/或 关键词搜索 相结合的方式。
- 类比 :当你询问一个复杂问题时,图书管理员根据你的问题,从编目系统中找出最相关的几本书或章节。
-
API与集成层(API & Integration Layer) :
- 功能 :提供简洁的编程接口(如Python SDK),让开发者能够轻松地“添加记忆”和“读取记忆”。它天然与LangChain、LlamaIndex等主流AI框架集成。
- 类比 :图书馆的借阅台,提供标准的借书、还书服务接口。
2.2 工作流程
一个典型的使用Cognee的AI应用工作流程如下:
- 记忆创建 :当用户与AI交互产生有价值的信息时(例如,用户说“我喜欢科幻小说,尤其是《三体》”),应用调用Cognee API,将该信息作为一条“记忆”存储起来,并与用户ID关联。
- 记忆处理 :Cognee在后台使用嵌入模型将该文本转化为向量,并存入指定的矢量数据库。
- 记忆检索 :当用户再次发起对话(例如,问“有什么新书推荐吗?”),应用首先将当前问题(或结合对话历史)发送给Cognee进行检索。
- 上下文增强 :Cognee返回与当前问题最相关的几条历史记忆(如“用户喜欢科幻小说”)。这些记忆被拼接到原始的LLM提示词中,形成最终的、富含上下文的提示。
- LLM生成 :增强后的提示被发送给LLM(如GPT-4、Claude或本地模型),LLM基于包含用户长期偏好的上下文,生成个性化回复(“鉴于您喜欢《三体》,我推荐《银河帝国》系列…”)。
这个过程实现了AI的“记忆-回忆-应用”循环。
3. 环境准备与项目搭建
接下来,我们将通过一个实战项目来演示Cognee的使用。我们将构建一个简单的“个性化读书助手”智能体,它能记住用户喜欢的书籍类型和作者,并在后续聊天中进行推荐。
3.1 技术栈与版本说明
- Python : 3.9+
- 核心库 :
cognee: Cognee核心库(请关注其GitHub仓库获取最新版本,本文基于其早期公开API概念演示)。langchain: 用于构建智能体链。版本0.1.x。openai: OpenAI官方SDK(用于调用GPT模型)。如果你使用其他模型,可替换为相应SDK。chromadb: 轻量级矢量数据库,作为Cognee的记忆存储后端。
- IDE : 任意你喜欢的代码编辑器,如VSCode、PyCharm。
- 虚拟环境 : 强烈建议使用
venv或conda创建隔离环境。
重要提示 :Cognee是一个快速迭代的开源项目,其API可能发生变化。以下示例代码旨在阐述核心概念和集成模式,实际使用时请务必参考其官方文档。
3.2 初始化项目与安装依赖
首先,创建项目目录并初始化虚拟环境。
# 创建项目目录
mkdir personalized-reading-assistant
cd personalized-reading-assistant
# 创建虚拟环境(以venv为例)
python -m venv venv
# 激活虚拟环境
# Windows:
venv\Scripts\activate
# Linux/Mac:
source venv/bin/activate
# 安装核心依赖
pip install langchain langchain-openai chromadb
# 注意:Cognee可能尚未发布到PyPI,或其包名有变。此处假设可通过pip安装其核心功能。
# 实际安装命令请以官方仓库为准,例如:pip install git+https://github.com/cognee-api/cognee.git
pip install cognee
创建项目结构:
personalized-reading-assistant/
├── main.py # 主程序入口
├── memory_system.py # 封装Cognee记忆操作
├── agent.py # 定义LangChain智能体
└── requirements.txt
将依赖写入 requirements.txt :
langchain>=0.1.0
langchain-openai>=0.0.5
chromadb>=0.4.22
openai>=1.12.0
cognee>=0.1.0 # 请替换为实际版本
4. 实战:构建带记忆的个性化读书助手
4.1 步骤一:配置Cognee记忆系统
我们首先创建一个模块来初始化和封装Cognee的记忆操作。
# memory_system.py
import os
from typing import List, Optional, Dict, Any
# 假设Cognee提供类似的API,这里根据其设计模式进行示意性编写
from cognee import CognitiveMemory # 示意类名
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Chroma
class MemorySystem:
"""
封装Cognee记忆系统的类。
负责记忆的存储、检索和与矢量数据库的交互。
"""
def __init__(self, user_id: str, persist_directory: str = "./chroma_db"):
"""
初始化记忆系统。
Args:
user_id: 唯一用户标识,用于隔离不同用户的记忆。
persist_directory: Chroma向量数据库持久化目录。
"""
self.user_id = user_id
self.persist_directory = os.path.join(persist_directory, user_id)
os.makedirs(self.persist_directory, exist_ok=True)
# 初始化嵌入模型(用于将文本转为向量)
# 注意:你需要设置OPENAI_API_KEY环境变量
self.embedding_function = OpenAIEmbeddings(model="text-embedding-3-small")
# 初始化向量数据库(Chroma作为后端)
self.vectorstore = Chroma(
collection_name=f"user_memories_{user_id}",
embedding_function=self.embedding_function,
persist_directory=self.persist_directory
)
# 初始化Cognee记忆核心(示意)
# 这里将向量存储传递给Cognee,由它来管理记忆的增删改查逻辑
self.memory_engine = CognitiveMemory(vector_store=self.vectorstore)
print(f"记忆系统已为用户 {user_id} 初始化。")
def add_memory(self, memory_text: str, metadata: Optional[Dict] = None):
"""
添加一条文本记忆。
Args:
memory_text: 需要记住的文本信息。
metadata: 额外的元数据,如记忆类型、时间戳等。
"""
if metadata is None:
metadata = {}
metadata.update({"user_id": self.user_id, "type": "preference"})
# 示意:Cognee引擎处理记忆(如生成摘要、提取关键词、创建向量等)
processed_memory = self.memory_engine.process_and_store(
content=memory_text,
metadata=metadata
)
print(f"记忆已添加: {memory_text[:50]}...")
return processed_memory
def search_memories(self, query: str, k: int = 3) -> List[str]:
"""
根据查询搜索相关记忆。
Args:
query: 搜索查询文本。
k: 返回最相关的记忆条数。
Returns:
相关记忆文本的列表。
"""
# 使用向量数据库进行语义搜索
docs = self.vectorstore.similarity_search(query, k=k)
memories = [doc.page_content for doc in docs]
return memories
def get_user_profile(self) -> str:
"""
获取用户的记忆摘要,形成简易“用户画像”。
在实际项目中,这里可以调用LLM对记忆进行总结。
"""
# 简单返回最近或最核心的几条记忆
all_docs = self.vectorstore.get() # 示意,实际API可能不同
if not all_docs.get('documents'):
return "该用户尚未提供任何偏好信息。"
# 这里简化处理:拼接最近几条记忆
profile_snippets = all_docs['documents'][:5]
profile = " | ".join(profile_snippets)
return f"已知用户偏好:{profile}"
4.2 步骤二:创建LangChain智能体
接下来,我们创建一个LangChain智能体,它将集成记忆系统,并在生成回复前动态检索相关记忆。
# agent.py
from langchain.agents import Tool, AgentExecutor, create_react_agent
from langchain.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
from memory_system import MemorySystem
from langchain.memory import ConversationBufferMemory
from langchain.tools import BaseTool
from typing import Type
class MemorySearchTool(BaseTool):
"""一个自定义LangChain工具,用于搜索用户记忆。"""
name = "search_user_memory"
description = "当需要根据用户的长期偏好或历史信息来回答问题或进行推荐时,使用此工具。输入应是一个描述当前需求或问题的查询语句。"
memory_system: MemorySystem = None
def _run(self, query: str) -> str:
"""执行工具。"""
if not self.memory_system:
return "记忆系统未初始化。"
memories = self.memory_system.search_memories(query, k=3)
if memories:
return "\n".join([f"- {m}" for m in memories])
else:
return "未找到相关的历史记忆。"
async def _arun(self, query: str) -> str:
"""异步执行(暂不实现)。"""
raise NotImplementedError("此工具不支持异步。")
def create_personal_agent(user_id: str):
"""
创建个性化智能体。
Args:
user_id: 用户ID,用于关联其专属记忆。
Returns:
配置好的智能体执行器。
"""
# 1. 初始化记忆系统
memory_sys = MemorySystem(user_id=user_id)
# 2. 初始化LLM
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0.7)
# 3. 创建记忆搜索工具,并注入记忆系统实例
memory_tool = MemorySearchTool()
memory_tool.memory_system = memory_sys
# 4. 定义其他可能用到的工具(示例)
# 例如,一个获取当前流行书籍的工具(这里用模拟工具)
from langchain.tools import tool
@tool
def get_trending_books(genre: str) -> str:
"""获取某个类型的流行书籍列表。输入应为书籍类型,如‘科幻’、‘历史’。"""
# 这里应该是调用真实API,我们模拟返回
mock_data = {
"科幻": ["《深渊的尽头》", "《星环纪元》", "《仿生人会梦见电子羊吗?》"],
"历史": ["《明朝那些事儿》", "《人类群星闪耀时》", "《丝绸之路》"]
}
return ", ".join(mock_data.get(genre, ["暂无数据"]))
# 工具列表
tools = [memory_tool, get_trending_books]
# 5. 创建智能体提示词模板
# 这个模板指导智能体何时使用工具,并融入记忆信息
prompt = PromptTemplate.from_template("""
你是一个个性化的读书助手,专门为用户{user_id}服务。
你的目标是利用你对用户的了解(他们的偏好、历史对话)来提供最贴切的推荐和帮助。
你拥有以下工具:
{tools}
在回答用户问题时,请遵循以下步骤:
1. 首先,思考用户的问题是否需要参考他的长期记忆(比如他过去喜欢什么书、讨厌什么作者)。
2. 如果需要,使用`search_user_memory`工具,输入一个能概括当前需求的查询词(例如:“用户喜欢的书籍类型”、“用户讨厌的作者”)。
3. 根据工具返回的记忆,结合你的知识和`get_trending_books`工具(如果需要当前流行信息),形成最终回答。
4. 如果用户的问题中包含了新的、值得长期记住的偏好(例如:“我其实更喜欢悬疑小说了”),请在你的回答中确认这一点,并**在回答结束后,单独用一行输出以下格式的命令,以便系统记录**:
`[MEMORY_TO_ADD]: 用户的新偏好或事实。`
当前对话历史:
{chat_history}
用户输入:{input}
开始思考:我应该使用工具吗?如果需要,用哪个?{agent_scratchpad}
""")
# 6. 创建对话记忆(短期,用于管理当前对话轮次)
conversation_memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
# 7. 创建智能体并返回执行器
agent = create_react_agent(llm, tools, prompt)
agent_executor = AgentExecutor(
agent=agent,
tools=tools,
memory=conversation_memory,
verbose=True, # 设置为True可以看到智能体的思考过程,生产环境可设为False
handle_parsing_errors=True
)
# 返回执行器和记忆系统(用于主程序添加记忆)
return agent_executor, memory_sys
4.3 步骤三:主程序与交互循环
最后,我们编写主程序,它将协调智能体对话和记忆的添加。
# main.py
import re
from agent import create_personal_agent
def main():
print("=== 个性化读书助手(带长期记忆)===")
user_id = input("请输入您的用户ID(用于加载您的专属记忆): ").strip() or "default_user"
# 创建智能体和记忆系统
agent_executor, memory_system = create_personal_agent(user_id)
print(f"\n您好,用户 {user_id}!我是您的读书助手。")
print("我可以记住您喜欢的书籍类型和作者,为您提供个性化推荐。")
print("输入 '退出' 或 'quit' 来结束对话。\n")
# 初始时,可以尝试获取一次用户画像并显示
profile = memory_system.get_user_profile()
print(f"[系统提示] {profile}\n")
while True:
user_input = input("您: ").strip()
if user_input.lower() in ['退出', 'quit', 'exit']:
print("再见!期待下次为您服务。")
break
try:
# 运行智能体
response = agent_executor.invoke({"input": user_input, "user_id": user_id})
full_response = response["output"]
# 解析响应,检查是否有需要添加的新记忆
memory_pattern = r'\[MEMORY_TO_ADD\]:\s*(.+)'
match = re.search(memory_pattern, full_response, re.DOTALL)
if match:
# 提取出需要添加的记忆文本
memory_to_add = match.group(1).strip()
# 从最终回复中移除记忆添加指令行
final_response = re.sub(memory_pattern, '', full_response).strip()
# 添加记忆到长期存储
memory_system.add_memory(memory_to_add, metadata={"source": "conversation"})
print(f"\n助手: {final_response}")
print(f"[系统] 已记录新偏好:{memory_to_add}")
else:
final_response = full_response
print(f"\n助手: {final_response}")
except Exception as e:
print(f"\n助手: 抱歉,处理您的请求时出现了问题。({e})")
print() # 空行分隔对话轮次
if __name__ == "__main__":
main()
5. 运行与效果演示
-
首次运行 :
python main.py输入用户ID(例如
alice)。系统会提示没有已知偏好。 -
提供偏好 :
您: 我喜欢刘慈欣的科幻小说,特别是《三体》。智能体会正常回复,并因为检测到新偏好,在回复末尾输出
[MEMORY_TO_ADD]: ...指令。我们的主程序会捕获这个指令,并将其存入Cognee记忆系统。 -
基于记忆的推荐 :
您: 最近有什么好书推荐吗?智能体会先调用
search_user_memory工具,搜索与“推荐好书”相关的记忆。工具会返回“我喜欢刘慈欣的科幻小说...”。智能体结合此记忆和get_trending_books工具(获取科幻类流行书),生成一个个性化推荐:“鉴于您喜欢刘慈欣和《三体》,我推荐您关注近期流行的科幻作品《深渊的尽头》和《星环纪元》...”。 -
记忆的演进 :
您: 其实我最近也对历史传记感兴趣了。同样,这个新偏好会被识别并存储。
-
后续对话 :无论何时,只要对话涉及书籍推荐,智能体都会检索所有相关记忆(科幻、历史传记),提供综合建议。
6. 常见问题与排查思路
在集成Cognee或类似记忆系统时,你可能会遇到以下问题:
| 问题现象 | 可能原因 | 排查思路与解决方案 |
|---|---|---|
| 记忆检索不相关 | 1. 嵌入模型不匹配或质量差。 2. 记忆文本过于冗长或噪声大。 3. 检索查询(query)构造不佳。 |
1. 尝试更换或微调嵌入模型(如 text-embedding-3-large )。 2. 在存储记忆前进行预处理:摘要、关键词提取、去噪。 3. 优化查询构造,可以尝试用LLM将用户问题重写为更适合搜索的格式。 |
| 记忆添加失败 | 1. 向量数据库连接错误。 2. Cognee处理过程出错。 3. 元数据格式不符合要求。 |
1. 检查向量数据库(如Chroma)是否正常运行,路径权限是否正确。 2. 查看Cognee日志或错误信息,确认其API调用方式。 3. 确保传入的metadata是字典格式,且不包含不可序列化的对象。 |
| 智能体不调用记忆工具 | 1. 工具描述(description)不清晰。 2. 提示词(Prompt)未有效引导。 3. LLM温度(temperature)设置过高,导致行为随机。 |
1. 优化工具的描述,明确其适用场景。 2. 强化提示词中关于“先思考是否需要记忆”的指令。 3. 适当降低LLM的temperature值,使其更遵循指令。 |
| 记忆混淆(用户间串扰) | 不同用户的记忆存储在同一个集合或未有效隔离。 | 确保初始化记忆系统时, user_id 被正确使用,并用于隔离向量数据库的集合(Collection)或命名空间(Namespace)。 |
| 性能问题 | 1. 记忆条目过多,检索慢。 2. 嵌入模型推理耗时。 |
1. 对记忆进行定期归档或摘要,减少活跃记忆数量。实现分页或分层检索。 2. 考虑使用更快的嵌入模型,或对向量索引进行优化(如HNSW参数调整)。 |
7. 最佳实践与工程建议
将长期记忆系统投入生产环境,需要考虑更多工程细节:
-
记忆的粒度与结构 :
- 不要存储原始对话日志 :应提取结构化信息(如
(用户, 喜欢, 科幻))或生成简洁的摘要。 - 分类存储 :可以为记忆打上类型标签(
preference,fact,goal),便于分类检索。 - 关联实体 :记忆不仅关联用户,还可以关联书籍、作者等实体,构建知识图谱。
- 不要存储原始对话日志 :应提取结构化信息(如
-
记忆的更新与遗忘 :
- 实现记忆更新 :用户偏好可能改变。系统应支持用新记忆覆盖或修正旧记忆,或为记忆添加置信度和时间戳,检索时优先考虑新鲜且高置信度的。
- 设计遗忘机制 :并非所有信息都需要永久记忆。可以设置TTL(生存时间)或基于重要性的遗忘策略。
-
隐私与安全 :
- 数据加密 :确保存储在向量数据库和磁盘上的记忆数据是加密的。
- 用户授权 :明确告知用户哪些数据会被记忆,并提供查看、编辑、删除个人记忆的入口。
- 合规性 :遵循相关数据保护法规(如GDPR)。
-
系统可观测性 :
- 记录检索日志 :记录每次检索的查询、返回的记忆以及最终LLM的回复,用于分析和优化记忆系统。
- 监控记忆质量 :定期抽样检查记忆的准确性和相关性。
-
与现有架构集成 :
- 作为微服务 :可以将Cognee封装成独立的记忆服务,通过gRPC或REST API供多个AI应用调用。
- 事件驱动 :用户行为事件(如购买、点赞、长时间阅读)可以自动触发记忆的添加或更新。
Cognee代表了一个重要的方向:为AI赋予持续学习和个人化的能力。通过本文的拆解和实战,你应该已经掌握了为其AI应用添加“记忆层”的核心思路与方法。从简单的用户偏好记忆开始,你可以逐步探索更复杂的记忆结构、更高效的检索算法以及与知识图谱的结合,最终打造出真正“懂你”的、具备长期陪伴感的智能应用。
更多推荐


所有评论(0)