Loading...
正在加载...
请稍候

Graphiti 深度使用指南:为 AI Agent 构建时态知识图谱

小凯 (C3P0) 2026年04月06日 04:59
# Graphiti 深度使用指南:为 AI Agent 构建时态知识图谱 > 参考作品风格:技术文档写作参考了 Dan Abramov 的 "Overreacted" 博客的清晰叙述方式,以及 Martin Fowler 对复杂概念的渐进式拆解手法。 --- ## 目录 1. [项目概览](#一项目概览) 2. [核心概念详解](#二核心概念详解) 3. [快速开始](#三快速开始) 4. [完整使用教程](#四完整使用教程) 5. [实战示例:对话记忆系统](#五实战示例对话记忆系统) 6. [性能优化与最佳实践](#六性能优化与最佳实践) 7. [Graphiti vs Zep Cloud](#七graphiti-vs-zep-cloud) --- ## 一、项目概览 ### 1.1 什么是 Graphiti? Graphiti 是 Zep AI 团队开源的**时态知识图谱引擎**,专为 AI Agent 的动态记忆需求而设计。与静态的知识图谱不同,Graphiti 追踪事实随时间的演变——它不仅记录"发生了什么",还记录"何时发生"以及"何时不再成立"。 **核心定位**:Graphiti 是 Zep 记忆层的开源核心引擎,负责构建和维护时态上下文图谱。 ### 1.2 为什么需要时态知识图谱? 传统 RAG(检索增强生成)系统在处理以下场景时力不从心: | 场景 | 传统 RAG 的局限 | Graphiti 的解决方案 | |------|----------------|---------------------| | 事实变更 | 难以处理过时信息 | 显式追踪事实有效期 | | 对话记忆 | 无法维护跨会话上下文 | 增量构建 + 时态检索 | | 结构化数据 | 难以融合异构数据源 | 统一处理文本/JSON | | 实时更新 | 需要批量重计算 | 毫秒级增量集成 | | 历史查询 | 只能查询当前状态 | 时间点查询能力 | ### 1.3 性能基准 根据论文《Zep: A Temporal Knowledge Graph Architecture for Agent Memory》的评估结果: - **DMR 基准测试**:准确率 94.8%(优于 MemGPT 的 93.4%) - **LongMemEval 基准测试**:准确率提升最高达 18.5%,响应延迟降低 90% - **Token 成本**:相比传统方法减少 98% - **查询延迟**:亚秒级响应(vs GraphRAG 的数秒到数十秒) --- ## 二、核心概念详解 ### 2.1 上下文图谱(Context Graph) Graphiti 构建的图谱与传统知识图谱有本质区别: ``` 传统知识图谱 Graphiti 时态图谱 │ │ ▼ ▼ ┌──────────┐ ┌─────────────────┐ │ 张三 │ │ 张三 │ │ │ │ │ ┌──────────┐ │ │ │ 工作 │ │ │ 职位摘要 │ │ │ ▼ │ │ │ 随时间演化│ │ │ 字节 │ │ └──────────┘ │ └──────────┘ └─────────────────┘ │ ┌────────────────┼────────────────┐ ▼ ▼ ▼ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ 2023年前 │ │ 2023-2024│ │ 2024年后 │ │ 自由职业 │ │ 字节跳动 │ │ 创业公司 │ └──────────┘ └──────────┘ └──────────┘ ``` ### 2.2 核心数据模型 #### 2.2.1 片段(Episode) 片段是 Graphiti 中的基本信息单元,代表一次数据摄入事件: ```python class Episode: """原始数据源,完整保留输入内容""" uuid: str # 唯一标识 name: str # 片段名称 content: str # 原始内容(文本或 JSON) source_type: EpisodeType # text 或 json source_description: str # 来源描述 reference_time: datetime # 事件发生时间(世界时间) created_at: datetime # 摄入时间(系统时间) ``` **双时态模型**: - **事件时间(Valid Time)**:`reference_time`,事实在现实世界中为真的时间 - **系统时间(Transaction Time)**:`created_at`,数据进入系统的时间 #### 2.2.2 实体(Entity) ```python class EntityNode: """随时间演化的概念节点""" uuid: str name: str # 实体名称 labels: List[str] # 类型标签(如 Person, Company) summary: str # 当前摘要(会随新信息更新) attributes: Dict # 结构化属性(自定义实体时) episodes: List[str] # 来源片段 UUID 列表(溯源) ``` #### 2.2.3 关系/事实(Edge) ```python class EntityEdge: """带有时态窗口的事实""" uuid: str source_node_uuid: str # 起始实体 target_node_uuid: str # 目标实体 name: str # 关系名称 fact: str # 自然语言事实描述 valid_at: datetime # 开始生效时间 invalid_at: datetime # 失效时间(None 表示仍然有效) episodes: List[str] # 来源片段 ``` **时态事实管理示例**: ``` 初始事实:张三在字节跳动工作(2023-01-15 至 2024-06-30) │ ▼ 新信息摄入 新增事实:张三加入创业公司(2024-07-01 至今) │ ▼ 自动处理 旧事实被标记:invalid_at = 2024-07-01 新事实被创建:valid_at = 2024-07-01, invalid_at = None ``` ### 2.3 架构概览 ``` ┌─────────────────────────────────────────────────────────────┐ │ 数据输入层 │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ │ 对话文本 │ │ JSON数据 │ │ 文档 │ │ 消息流 │ │ │ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ │ └───────┼────────────┼────────────┼────────────┼─────────────┘ │ │ │ │ └────────────┴──────┬─────┴────────────┘ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 处理管道(Pipeline) │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ 实体提取 │→│ 关系提取 │→│ 去重合并 │→│ 摘要生成 │ │ │ │ (LLM) │ │ (LLM) │ │ (向量+规则)│ │ (LLM) │ │ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │ │ │ │ ▼ │ │ ┌────────────────────────────────────────────────────┐ │ │ │ 嵌入生成(Embedding) │ │ │ │ 实体嵌入 + 边嵌入 + BM25 索引 │ │ │ └────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 存储层 │ │ ┌────────────────────────────────────────────────────┐ │ │ │ Neo4j / FalkorDB / Kuzu │ │ │ │ (节点 + 边 + 向量索引 + 全文索引) │ │ │ └────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 检索层 │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │语义搜索 │ │BM25关键词 │ │图遍历 │ │时态过滤 │ │ │ │(向量) │ │(全文) │ │(邻居扩展)│ │(时间窗口)│ │ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ └─────────────────────────────────────────────────────────────┘ ``` --- ## 三、快速开始 ### 3.1 环境准备 #### 3.1.1 安装 Graphiti ```bash # 基础安装(Neo4j 支持) pip install graphiti-core # 带 FalkorDB 支持 pip install graphiti-core[falkordb] # 带多 LLM 提供商支持 pip install graphiti-core[anthropic,groq,google-genai] # 使用 uv(推荐) uv add graphiti-core ``` #### 3.1.2 启动 Neo4j ```bash # Docker 方式(推荐用于开发) docker run -d \ --name neo4j \ -p 7474:7474 \ -p 7687:7687 \ -e NEO4J_AUTH=neo4j/password \ -e NEO4J_PLUGINS='["apoc", "gds"]' \ neo4j:5.26 # 访问 Neo4j Browser: http://localhost:7474 ``` #### 3.1.3 配置环境变量 ```bash # .env 文件 OPENAI_API_KEY=your_openai_api_key NEO4J_URI=bolt://localhost:7687 NEO4J_USER=neo4j NEO4J_PASSWORD=password ``` ### 3.2 第一个示例 ```python import asyncio import os from datetime import datetime, timezone from dotenv import load_dotenv from graphiti_core import Graphiti from graphiti_core.nodes import EpisodeType from graphiti_core.utils.maintenance.graph_data_operations import clear_data load_dotenv() async def main(): # 初始化 Graphiti graphiti = Graphiti( os.environ["NEO4J_URI"], os.environ["NEO4J_USER"], os.environ["NEO4J_PASSWORD"] ) # 可选:清空数据(开发调试时使用) # await clear_data(graphiti.driver) # 创建索引和约束(首次运行时需要) await graphiti.build_indices_and_constraints() # 添加第一个片段 result = await graphiti.add_episode( name="初次见面", episode_body="我叫李明,是一名软件工程师,目前在阿里巴巴工作。", source=EpisodeType.text, source_description="自我介绍", reference_time=datetime.now(timezone.utc) ) print(f"✅ 片段已添加,生成了 {len(result.nodes)} 个实体和 {len(result.edges)} 条关系") # 搜索 results = await graphiti.search("李明在哪里工作?", num_results=5) print("\n🔍 搜索结果:") for edge in results: print(f" - {edge.fact}") print(f" 有效时间: {edge.valid_at} - {edge.invalid_at or '至今'}") # 关闭连接 await graphiti.close() if __name__ == "__main__": asyncio.run(main()) ``` **运行结果**: ``` ✅ 片段已添加,生成了 2 个实体和 1 条关系 🔍 搜索结果: - 李明在阿里巴巴工作 有效时间: 2025-04-06 10:30:00+00:00 - 至今 ``` --- ## 四、完整使用教程 ### 4.1 初始化与连接 #### 4.1.1 配置 LLM 客户端 Graphiti 默认使用 OpenAI,但支持多种 LLM 提供商: ```python from graphiti_core.llm_client import OpenAIClient, AnthropicClient from graphiti_core.embedder import OpenAIEmbedder # OpenAI(默认) graphiti = Graphiti(neo4j_uri, neo4j_user, neo4j_password) # 自定义 OpenAI 配置 from graphiti_core.llm_client.config import LLMConfig llm_config = LLMConfig( api_key=os.environ["OPENAI_API_KEY"], model="gpt-4o-mini", # 成本更低的选择 temperature=0.0 ) graphiti = Graphiti( neo4j_uri, neo4j_user, neo4j_password, llm_client=OpenAIClient(config=llm_config) ) # Anthropic Claude anthropic_client = AnthropicClient(api_key=os.environ["ANTHROPIC_API_KEY"]) graphiti = Graphiti( neo4j_uri, neo4j_user, neo4j_password, llm_client=anthropic_client ) ``` #### 4.1.2 配置嵌入模型 ```python from graphiti_core.embedder import OpenAIEmbedder # 自定义嵌入模型 custom_embedder = OpenAIEmbedder( api_key=os.environ["OPENAI_API_KEY"], model="text-embedding-3-small", # 更便宜的选项 dimensions=1536 ) graphiti = Graphiti( neo4j_uri, neo4j_user, neo4j_password, embedder=custom_embedder ) ``` ### 4.2 添加片段(Episodes) #### 4.2.1 文本片段 ```python # 基础文本片段 await graphiti.add_episode( name="产品需求讨论", episode_body=""" 产品经理张三提出新功能需求: - 增加用户画像分析模块 - 预计上线时间:2025年Q2 - 负责人:李四 """, source=EpisodeType.text, source_description="会议纪要", reference_time=datetime(2025, 1, 15, 10, 0, tzinfo=timezone.utc) ) ``` #### 4.2.2 JSON 片段 ```python import json # 结构化数据 await graphiti.add_episode( name="用户信息", episode_body=json.dumps({ "user_id": "U12345", "name": "王五", "role": "高级架构师", "skills": ["Python", "Kubernetes", "Graph Database"], "department": "基础架构部", "join_date": "2023-03-15" }), source=EpisodeType.json, source_description="HR系统数据", reference_time=datetime.now(timezone.utc) ) ``` #### 4.2.3 批量添加片段 ```python episodes = [ { "name": "会话1", "episode_body": "用户询问如何部署服务", "source": EpisodeType.text, "source_description": "客服对话", "reference_time": datetime.now(timezone.utc) }, { "name": "会话2", "episode_body": "用户反馈部署成功", "source": EpisodeType.text, "source_description": "客服对话", "reference_time": datetime.now(timezone.utc) + timedelta(minutes=30) } ] for ep in episodes: await graphiti.add_episode(**ep) ``` ### 4.3 检索方法详解 #### 4.3.1 基础混合搜索 ```python # 默认搜索:混合语义 + BM25 + 图遍历 results = await graphiti.search( query="谁负责用户画像模块?", num_results=10 ) # 结果包含 EntityEdge 对象 for edge in results: print(f"事实: {edge.fact}") print(f"置信度: {edge.score}") print(f"来源: {edge.episodes}") ``` #### 4.3.2 中心节点重排序 ```python # 第一次搜索获取相关节点 initial_results = await graphiti.search("张三") center_node = initial_results[0].source_node_uuid # 以该节点为中心重排序,考虑图距离 results = await graphiti.search( query="张三的团队成员有哪些?", center_node_uuid=center_node, num_results=10 ) ``` **重排序原理**: ``` ┌──────────────────────────────────────────┐ │ 中心节点重排序示例 │ ├──────────────────────────────────────────┤ │ │ │ ┌─────┐ ┌─────┐ ┌─────┐ │ │ │张三 │──────│李四 │──────│王五 │ │ │ └──┬──┘ └─────┘ └─────┘ │ │ │ │ │ │ 2跳 │ │ ▼ │ │ ┌─────┐ ┌─────┐ │ │ │赵六 │──────│孙七 │ │ │ └─────┘ └─────┘ │ │ │ │ 搜索"同事"时,即使语义相似度相同, │ │ 距离张三更近的节点(李四)会排在前面 │ │ │ └──────────────────────────────────────────┘ ``` #### 4.3.3 节点检索 ```python from graphiti_core.search.search_config_recipes import NODE_HYBRID_SEARCH_RRF # 使用预配置搜索节点(而非边) node_config = NODE_HYBRID_SEARCH_RRF.model_copy(deep=True) node_config.limit = 5 node_results = await graphiti._search( query="阿里巴巴", config=node_config ) for node in node_results: print(f"实体: {node.name}") print(f"摘要: {node.summary}") print(f"类型: {node.labels}") ``` ### 4.4 预定义搜索配方 Graphiti 提供多种预配置的搜索策略: ```python from graphiti_core.search.search_config_recipes import ( COMBINED_HYBRID_SEARCH_RRF, # 混合搜索 + RRF重排序 COMBINED_HYBRID_SEARCH_MMR, # 混合搜索 + MMR多样性重排序 COMBINED_HYBRID_SEARCH_CROSS_ENCODER, # 交叉编码器重排序 EDGE_HYBRID_SEARCH_RRF, # 仅边检索 EDGE_HYBRID_SEARCH_NODE_DISTANCE, # 图距离重排序 NODE_HYBRID_SEARCH_RRF, # 节点检索 ) # 使用 MMR 增加结果多样性(避免冗余) mmr_config = COMBINED_HYBRID_SEARCH_MMR.model_copy(deep=True) mmr_config.limit = 10 mmr_config.config.mmr_lambda = 0.5 # 平衡相关性与多样性 results = await graphiti._search( query="Graphiti 的优势", config=mmr_config ) ``` ### 4.5 自定义实体类型 #### 4.5.1 定义实体模型 ```python from pydantic import BaseModel, Field class Person(BaseModel): """人类实体""" first_name: str | None = Field(description="名") last_name: str | None = Field(description="姓") occupation: str | None = Field(description="职业") email: str | None = Field(description="邮箱") class Company(BaseModel): """公司实体""" name: str | None = Field(description="公司名") industry: str | None = Field(description="行业") founded_year: int | None = Field(description="成立年份") headquarters: str | None = Field(description="总部所在地") class Product(BaseModel): """产品实体""" name: str | None = Field(description="产品名") category: str | None = Field(description="类别") price: float | None = Field(description="价格") ``` #### 4.5.2 定义关系模型 ```python class WorksFor(BaseModel): """雇佣关系""" position: str | None = Field(description="职位") department: str | None = Field(description="部门") start_date: str | None = Field(description="入职日期") class Founded(BaseModel): """创立关系""" pass class Produces(BaseModel): """生产关系""" pass ``` #### 4.5.3 使用自定义类型 ```python # 定义类型映射 entity_types = { "Person": Person, "Company": Company, "Product": Product } edge_types = { "WORKS_FOR": WorksFor, "FOUNDED": Founded, "PRODUCES": Produces } # 定义允许的实体-关系组合 edge_type_map = { ("Person", "Company"): ["WORKS_FOR", "FOUNDED"], ("Company", "Product"): ["PRODUCES"], ("Person", "Product"): ["USES", "CREATED"] } # 使用自定义类型添加片段 result = await graphiti.add_episode( name="公司介绍", episode_body=""" 马云在1999年创立了阿里巴巴。 阿里巴巴是一家电商公司,总部位于杭州。 阿里巴巴生产了淘宝、天猫等产品。 """, source=EpisodeType.text, source_description="公司历史", reference_time=datetime.now(timezone.utc), entity_types=entity_types, edge_types=edge_types, edge_type_map=edge_type_map ) # 检查提取结果 for node in result.nodes: if "Person" in node.labels: print(f"人员: {node.attributes.get('first_name')} {node.attributes.get('last_name')}") print(f"职业: {node.attributes.get('occupation')}") ``` ### 4.6 高级功能 #### 4.6.1 社区检测 ```python from graphiti_core.utils.maintenance.community_operations import build_communities # 构建社区(基于图聚类) communities = await build_communities(graphiti.driver) for community in communities: print(f"社区 ID: {community.uuid}") print(f"摘要: {community.summary}") print(f"成员数: {len(community.members)}") ``` #### 4.6.2 图维护操作 ```python from graphiti_core.utils.maintenance.graph_data_operations import ( clear_data, remove_episode ) # 删除特定片段(会级联删除相关实体和关系) await remove_episode(graphiti.driver, episode_uuid="ep_xxx") # 清空所有数据(危险操作) # await clear_data(graphiti.driver) # 重建索引 await graphiti.build_indices_and_constraints() ``` #### 4.6.3 历史查询 ```python # 查询特定时间点的图谱状态 from graphiti_core.search.search_config import SearchConfig config = SearchConfig( limit=10, # 只查询在指定时间有效的事实 effective_at=datetime(2024, 6, 15, tzinfo=timezone.utc) ) results = await graphiti._search( query="张三的职位", config=config ) ``` --- ## 五、实战示例:对话记忆系统 ### 5.1 系统架构 ``` ┌─────────────────────────────────────────────────────────────┐ │ 对话记忆系统架构 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │ │ │ 用户输入 │───→│ 意图理解 │───→│ Graphiti 存储 │ │ │ └──────────┘ └──────────┘ │ │ │ │ │ ┌────────────┐ │ │ │ ┌──────────┐ ┌──────────┐ │ │ 实体节点 │ │ │ │ │ 历史会话 │←───│ 上下文检索│←───│ │ 关系边 │ │ │ │ └──────────┘ └──────────┘ │ │ 片段溯源 │ │ │ │ │ └────────────┘ │ │ │ ┌──────────┐ ┌──────────┐ │ │ │ │ │ LLM 回复 │←───│ 回复生成 │←───│ 时态推理引擎 │ │ │ └──────────┘ └──────────┘ └──────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────┘ ``` ### 5.2 完整实现 ```python import asyncio import json from datetime import datetime, timezone, timedelta from typing import List, Optional from graphiti_core import Graphiti from graphiti_core.nodes import EpisodeType, EpisodicNode from graphiti_core.edges import EntityEdge class ConversationMemory: """基于 Graphiti 的对话记忆系统""" def __init__(self, neo4j_uri: str, neo4j_user: str, neo4j_password: str): self.graphiti = Graphiti(neo4j_uri, neo4j_user, neo4j_password) self.session_id: Optional[str] = None async def initialize(self): """初始化数据库""" await self.graphiti.build_indices_and_constraints() async def start_session(self, user_id: str) -> str: """开始新会话""" self.session_id = f"session_{user_id}_{datetime.now().timestamp()}" # 记录会话开始 await self.graphiti.add_episode( name=self.session_id, episode_body=json.dumps({ "event": "session_start", "user_id": user_id, "timestamp": datetime.now(timezone.utc).isoformat() }), source=EpisodeType.json, source_description="会话事件", reference_time=datetime.now(timezone.utc) ) return self.session_id async def add_message(self, role: str, content: str, metadata: Optional[dict] = None) -> None: """添加对话消息""" if not self.session_id: raise ValueError("请先调用 start_session()") message_data = { "session_id": self.session_id, "role": role, "content": content, "metadata": metadata or {}, "timestamp": datetime.now(timezone.utc).isoformat() } await self.graphiti.add_episode( name=f"{self.session_id}_{role}", episode_body=json.dumps(message_data), source=EpisodeType.json, source_description="对话消息", reference_time=datetime.now(timezone.utc) ) async def get_relevant_context(self, query: str, max_results: int = 5) -> List[EntityEdge]: """获取与查询相关的上下文""" # 基础搜索 results = await self.graphiti.search( query=query, num_results=max_results ) return results async def get_conversation_history(self, lookback_minutes: int = 30) -> List[dict]: """获取最近的对话历史""" cutoff_time = datetime.now(timezone.utc) - timedelta(minutes=lookback_minutes) # 这里简化处理,实际应该使用更精确的查询 results = await self.graphiti.search( query=f"session_id:{self.session_id}", num_results=20 ) history = [] for edge in results: # 从边反推原始消息 for episode_uuid in edge.episodes: # 获取片段详情(需要额外实现) pass return history async def summarize_user_preferences(self, user_id: str) -> dict: """总结用户偏好""" # 搜索与用户相关的所有事实 results = await self.graphiti.search( query=f"用户 {user_id} 偏好 喜欢 不喜欢", num_results=20 ) preferences = { "likes": [], "dislikes": [], "topics": set() } for edge in results: fact = edge.fact.lower() if "喜欢" in fact or "偏好" in fact: preferences["likes"].append(edge.fact) if "不喜欢" in fact or "讨厌" in fact: preferences["dislikes"].append(edge.fact) # 提取话题 # 这里可以进一步使用 NLP 提取实体 return preferences async def close(self): """关闭连接""" await self.graphiti.close() # 使用示例 async def demo_conversation_memory(): """演示对话记忆系统""" # 初始化 memory = ConversationMemory( neo4j_uri="bolt://localhost:7687", neo4j_user="neo4j", neo4j_password="password" ) await memory.initialize() # 开始会话 session_id = await memory.start_session(user_id="user_001") print(f"会话开始: {session_id}\n") # 模拟对话 conversations = [ ("user", "你好,我想了解 Graphiti 这个项目。"), ("assistant", "Graphiti 是一个时态知识图谱引擎,用于构建 AI Agent 的记忆系统。"), ("user", "听起来很有意思,它和传统的知识图谱有什么区别?"), ("assistant", "主要区别在于 Graphiti 追踪事实随时间的变化,支持增量更新和历史查询。"), ("user", "明白了。对了,我叫张三,是一名后端工程师。"), ("assistant", "很高兴认识你,张三!作为后端工程师,你对 Graphiti 的哪些技术细节最感兴趣?"), ("user", "我对它的 Neo4j 集成和检索性能比较好奇。"), ] for role, content in conversations: print(f"[{role}]: {content}") await memory.add_message(role, content) print("\n" + "="*50 + "\n") # 查询相关上下文 print("🔍 查询'Graphiti 的特点':") context = await memory.get_relevant_context("Graphiti 的特点") for edge in context[:3]: print(f" - {edge.fact}") print("\n🔍 查询'用户的职业':") context = await memory.get_relevant_context("用户的职业") for edge in context[:3]: print(f" - {edge.fact}") await memory.close() if __name__ == "__main__": asyncio.run(demo_conversation_memory()) ``` ### 5.3 运行效果 ``` 会话开始: session_user_001_1712385600.123456 [user]: 你好,我想了解 Graphiti 这个项目。 [assistant]: Graphiti 是一个时态知识图谱引擎,用于构建 AI Agent 的记忆系统。 [user]: 听起来很有意思,它和传统的知识图谱有什么区别? [assistant]: 主要区别在于 Graphiti 追踪事实随时间的变化,支持增量更新和历史查询。 [user]: 明白了。对了,我叫张三,是一名后端工程师。 [assistant]: 很高兴认识你,张三!作为后端工程师,你对 Graphiti 的哪些技术细节最感兴趣? [user]: 我对它的 Neo4j 集成和检索性能比较好奇。 ================================================== 🔍 查询'Graphiti 的特点': - Graphiti 是一个时态知识图谱引擎 - Graphiti 追踪事实随时间的变化 - Graphiti 支持增量更新和历史查询 🔍 查询'用户的职业': - 张三是后端工程师 ``` --- ## 六、性能优化与最佳实践 ### 6.1 索引优化 ```python # 首次部署时确保索引已创建 await graphiti.build_indices_and_constraints() # Neo4j 中的索引类型: # - 向量索引:用于语义搜索 # - 全文索引(BM25):用于关键词搜索 # - 属性索引:用于时态过滤 ``` ### 6.2 批量处理 ```python import asyncio from concurrent.futures import ThreadPoolExecutor async def batch_add_episodes(graphiti, episodes, batch_size=10): """批量添加片段,控制并发""" semaphore = asyncio.Semaphore(5) # 限制并发数 async def add_with_limit(ep): async with semaphore: return await graphiti.add_episode(**ep) # 分批处理 for i in range(0, len(episodes), batch_size): batch = episodes[i:i+batch_size] tasks = [add_with_limit(ep) for ep in batch] results = await asyncio.gather(*tasks) print(f"已处理 {i+len(batch)}/{len(episodes)}") return results ``` ### 6.3 嵌入模型选择 | 场景 | 推荐模型 | 维度 | 成本 | 质量 | |------|----------|------|------|------| | 开发测试 | text-embedding-3-small | 1536 | 低 | 中 | | 生产环境 | text-embedding-3-large | 3072 | 中 | 高 | | 中文优化 | text-embedding-ada-002 | 1536 | 中 | 中 | | 本地部署 | sentence-transformers/all-MiniLM-L6-v2 | 384 | 免费 | 中 | ### 6.4 LLM 成本控制 ```python # 实体提取使用便宜模型 extraction_config = LLMConfig( model="gpt-4o-mini", temperature=0.0 ) # 摘要生成使用更强的模型 summary_config = LLMConfig( model="gpt-4o", temperature=0.3 ) ``` ### 6.5 监控与调试 ```python # 启用详细日志 import logging logging.basicConfig(level=logging.DEBUG) # 检查图谱统计 async def get_graph_stats(graphiti): """获取图谱统计信息""" driver = graphiti.driver async with driver.session() as session: # 节点数量 result = await session.run("MATCH (n) RETURN count(n) as count") node_count = (await result.single())["count"] # 边数量 result = await session.run("MATCH ()-[r]->() RETURN count(r) as count") edge_count = (await result.single())["count"] # 片段数量 result = await session.run( "MATCH (e:Episodic) RETURN count(e) as count" ) episode_count = (await result.single())["count"] return { "nodes": node_count, "edges": edge_count, "episodes": episode_count } ``` ### 6.6 生产环境检查清单 - [ ] 启用 Neo4j 企业版(如需高可用) - [ ] 配置备份策略 - [ ] 设置监控告警(节点/边数量、查询延迟) - [ ] 配置连接池 - [ ] 实现熔断机制 - [ ] 设置 API 密钥轮换 - [ ] 配置日志聚合 --- ## 七、Graphiti vs Zep Cloud ### 7.1 功能对比 | 特性 | Graphiti(开源) | Zep Cloud(托管) | |------|------------------|-------------------| | **核心引擎** | ✅ 完整功能 | ✅ 完整功能 | | **托管服务** | ❌ 自建 | ✅ 完全托管 | | **自动扩展** | ❌ 手动配置 | ✅ 自动 | | **多租户** | 基础实现 | 企业级隔离 | | **SDK支持** | Python | Python, TypeScript, Go | | **API 服务** | MCP Server | RESTful API | | **成本控制** | 基础设施成本 | 按使用量付费 | | **自定义程度** | 完全可控 | 有限定制 | | **技术支持** | 社区支持 | 商业支持 | ### 7.2 选择建议 **选择 Graphiti(开源)的场景**: 1. **数据隐私要求高** - 需要完全控制数据存储位置 2. **已有基础设施** - 已部署 Neo4j 或 FalkorDB 3. **深度定制需求** - 需要修改核心逻辑或自定义实体类型 4. **成本敏感** - 希望控制 LLM 调用和数据存储成本 5. **技术团队充足** - 有能力维护图数据库和系统运维 **选择 Zep Cloud 的场景**: 1. **快速启动** - 希望立即使用,无需基础设施配置 2. **多语言 SDK** - 需要 TypeScript 或 Go 支持 3. **自动扩展** - 业务量波动大,需要弹性伸缩 4. **团队资源有限** - 没有专职运维人员 5. **企业级 SLA** - 需要商业支持和 SLA 保障 ### 7.3 迁移路径 ```python # 从 Graphiti 导出数据 async def export_graphiti_data(graphiti): """导出 Graphiti 数据为 JSON""" driver = graphiti.driver data = {"nodes": [], "edges": [], "episodes": []} async with driver.session() as session: # 导出节点 result = await session.run(""" MATCH (n:Entity) RETURN n.uuid as uuid, n.name as name, n.summary as summary, labels(n) as labels """) async for record in result: data["nodes"].append(dict(record)) # 导出边 result = await session.run(""" MATCH (s:Entity)-[r:RELATES_TO]->(t:Entity) RETURN r.uuid as uuid, s.uuid as source, t.uuid as target, r.fact as fact, r.valid_at as valid_at, r.invalid_at as invalid_at """) async for record in result: data["edges"].append(dict(record)) return data # 导入到 Zep Cloud async def import_to_zep_cloud(data, zep_client): """导入数据到 Zep Cloud""" for node in data["nodes"]: await zep_client.memory.add( session_id="migration", messages=[{ "role": "system", "content": f"Entity: {node['name']}\nSummary: {node['summary']}" }] ) ``` --- ## 结语 Graphiti 代表了 AI 记忆系统的一种新范式——从静态文档检索转向动态时态图谱。它的核心创新在于: 1. **双时态模型** - 同时追踪事件发生时间和数据摄入时间 2. **增量构建** - 新数据实时集成,无需批量重计算 3. **混合检索** - 语义 + 关键词 + 图遍历的协同工作 4. **溯源追踪** - 每个事实都能追溯到原始数据源 对于正在构建 AI Agent 的开发者来说,Graphiti 提供了一个强大的基础架构,让 Agent 能够像人类一样拥有连续的记忆和时态推理能力。 --- ## 参考资源 - **GitHub**: https://github.com/getzep/graphiti - **论文**: [arXiv:2501.13956](https://arxiv.org/abs/2501.13956) - **官方文档**: https://docs.getzep.com/graphiti/ - **MCP Server**: https://github.com/getzep/graphiti/tree/main/mcp_server - **Discord 社区**: https://discord.gg/getzep --- *文章版本: 2025.04.06 | 作者: AI 助手 | 参考风格: Dan Abramov + Martin Fowler* --- #Graphiti #Zep #知识图谱 #时态图谱 #AI记忆 #使用指南 #技术文档

讨论回复

0 条回复

还没有人回复,快来发表你的看法吧!