← 返回 Semantica 专题首页 🚀 SEMANTICA · COOKBOOK · 进阶系列

高级上下文工程:智能体的大脑

Semantica 官方 Cookbook 中文翻译 · 第 30 / 37 篇

📦 semantica 🕸️ 知识图谱 🔎 GraphRAG

欢迎来到 Semantica 上下文工程的大师课。本 notebook 演示了如何为你的 AI 智能体构建一个生产级的记忆系统。

与那些在会话结束后就忘记一切的简单聊天机器人不同,一个上下文感知智能体需要: * 长期记忆:能够回忆起数周前的事实。 * 结构化知识:理解实体(人物、项目、主题)之间是如何连接的。 * 混合检索:将模糊的文本搜索与精确的图谱遍历相结合。

1学习目标

在本教程中,我们将: 1. 初始化生产级存储:用真实的向量存储(FAISS)和图存储(Neo4j)替换玩具示例。 2. 构建智能体上下文:配置负责编排记忆的中央大脑。 3. 摄取知识:存储复杂文档并自动抽取实体。 4. 注入关系:手动教会智能体关于世界中各种连接的知识。 5. 执行 GraphRAG:执行高级查询,在知识图谱中"跳跃"以找到标准 RAG 会遗漏的答案。 6. 管理生命周期:学会修剪旧记忆并保持系统健康。


21. 安装

要开始使用,只需安装该包:

# 安装 semantica
pip install semantica
# 安装 Semantica 包
!pip install -qU semantica
import sys
import os
import time
from typing import Any, List, Dict, Optional

# 将项目根目录添加到路径以导入 semantica
sys.path.append(os.path.abspath(os.path.join(os.getcwd(), "../../")))

# 核心导入
from semantica.context import AgentContext, ContextGraph, AgentMemory
from semantica.vector_store import VectorStore
from semantica.graph_store import GraphStore

print("Libraries imported successfully.")

32. 初始化存储后端

现在我们将连接到持久化存储层。Semantica 将这些抽象在统一接口之后,因此你可以在不改变应用逻辑的情况下更换后端(例如,从 FAISS 切换到 Weaviate)。

向量存储(图书馆)

保存记忆和文档的内容,按语义含义建立索引。

try:
    # 初始化 FAISS 向量存储
    # 你也可以使用:backend="weaviate"、backend="qdrant" 等。
    vs = VectorStore(backend="faiss", dimension=768)
    print("VectorStore initialized (Backend: FAISS)")
except ImportError:
    print("FAISS not installed. Using in-memory fallback (not persistent).")
    vs = VectorStore(backend="inmemory", dimension=768)
except Exception as e:
    print(f"VectorStore Error: {e}")
    vs = None

图存储(地图)

保存实体之间的连接。这对于推理至关重要。

try:
    # 初始化 Neo4j 图存储
    # 确保你的 Docker 容器正在运行!
    gs = GraphStore(
        backend="neo4j",
        uri="bolt://localhost:7687",
        user="neo4j",
        password="password"
    )

    # 测试连接
    if gs.connect():
        print("GraphStore connected (Backend: Neo4j)")
    else:
        raise ConnectionError("Could not connect to Neo4j")

except Exception as e:
    print(f"GraphStore Connection Failed: {e}")
    print("   Switching to in-memory ContextGraph (Non-persistent fallback)")
    gs = ContextGraph() # 回退实现

43. 智能体上下文

AgentContext 是高层编排器。它位于向量存储和图存储之上,管理信息的流动。

GraphRAG 的配置: * use_graph_expansion=True:检索时,不要只看文档本身,还要看它的邻居。 * max_expansion_hops=2:要遍历多远?(例如,A -> B -> C)。 * hybrid_alpha=0.6:权重。0.0 是纯向量,1.0 是纯图谱。0.6 略微偏向图谱。

# 基于向量存储与图谱存储构建智能体上下文
if vs:
    context = AgentContext(
        vector_store=vs,
        knowledge_graph=gs,
        retention_days=90,          # 记住 3 个月的内容
        use_graph_expansion=True,   # 启用 GraphRAG
        max_expansion_hops=2,       # 2 跳推理
        hybrid_alpha=0.6            # 平衡检索
    )
    print("Agent Context is online and ready.")
else:
    print("Cannot proceed without VectorStore.")

54. 摄取:教会智能体

我们可以存储不同类型的信息。系统足够智能,能够区分对话记忆和事实性文档。

A. 情景记忆(对话)

这些是交互的原始日志。它们提供了"个人"历史。

user_id = "user_123"
session_id = "session_alpha"

# 存储一条用户偏好
mem_id = context.store(
    content="I am working on a new project called 'Project Apollo' which uses Python and React.",
    conversation_id=session_id,
    user_id=user_id,
    metadata={"type": "user_preference"}
)
print(f"Memory Stored: {mem_id}")

B. 语义知识(文档)

当我们输入文档时,我们希望抽取实体将它们链接起来

(注意:在真实设置中,这会使用 LLM 来解析实体。这里我们使用上下文模块原生的抽取能力。)

documents = [
    {
        "content": "Project Apollo is a next-gen web framework designed for high scalability.",
        "metadata": {"source": "internal_wiki", "category": "projects"}
    },
    {
        "content": "Python 3.12 introduces significant performance improvements for async workloads.",
        "metadata": {"source": "tech_news", "category": "languages"}
    }
]

# 存储文档并触发图谱构建
stats = context.store(
    documents,
    extract_entities=True,      # 从文本中抽取实体
    extract_relationships=True, # 推断关系
    link_entities=True          # 连接到现有图谱节点
)

print("Knowledge Ingestion Stats:", stats)

65. 图谱工程:手动注入

有时自动抽取还不够。你想要强制执行特定的业务逻辑或关系。我们可以使用 build_graph 手动注入节点和边。

我们将定义: * 用户(Alice) * 角色(Admin) * 项目(Apollo) * 关系:Alice 管理 Project Apollo。

# 1. 定义节点
entities = [
    {"id": "alice", "type": "PERSON", "text": "Alice", "properties": {"role": "Admin"}},
    {"id": "project_apollo", "type": "PROJECT", "text": "Project Apollo"},
    {"id": "python", "type": "TECH", "text": "Python"},
    {"id": "react", "type": "TECH", "text": "React"}
]

# 2. 定义边(知识)
relationships = [
    {"source": "alice", "target": "project_apollo", "type": "MANAGES", "weight": 1.0},
    {"source": "project_apollo", "target": "python", "type": "USES_TECH", "weight": 1.0},
    {"source": "project_apollo", "target": "react", "type": "USES_TECH", "weight": 1.0}
]

# 3. 注入图谱
graph_stats = context.build_graph(
    entities=entities,
    relationships=relationships
)

print("Manual Graph Build Complete:", graph_stats)

可视化图谱逻辑

让我们直接查询图谱,看看 "Project Apollo" 长什么样。

# 用于打印图谱邻居的辅助函数
def inspect_node(node_id):
    if hasattr(gs, "get_neighbors"):
        neighbors = gs.get_neighbors(node_id)
        print(f"\nNeighbors of '{node_id}':")
        for n in neighbors:
            # 处理不同存储之间不同的返回格式
            rel_type = n.get('relationship') or n.get('type') or 'linked'
            target = n.get('id') or n.get('node_id')
            print(f"   └── [{rel_type}] ──> {target}")
    else:
        print("Graph store does not support neighbor inspection.")

inspect_node("project_apollo")

76. 混合检索(GraphRAG)

现在到了神奇的部分。我们提出一个需要串联线索的问题。

查询"谁负责 Python Web 框架项目?"

逻辑流程: 1. 向量搜索:找到 "Project Apollo"(被描述为 Web 框架)。 2. 图谱扩展:查看图谱中的 "Project Apollo"。 3. 发现:看到 (Alice)-[MANAGES]->(Project Apollo)。 4. 结果:返回 Alice,尽管她的名字并不在项目描述文本中!

query = "Who is responsible for the Python web framework project?"
print(f"Asking: '{query}'...\n")

results = context.retrieve(
    query,
    max_results=3,
    use_graph=True,         # 对找到 Alice 至关重要
    expand_graph=True,      # 跳到邻居
    include_entities=True   # 返回结构化实体数据
)

print(f"Retrieved {len(results)} context items:\n")

for i, res in enumerate(results, 1):
    print(f"{i}. [Score: {res['score']:.2f}] {res['content'][:120]}...")

    # 我们找到图谱连接了吗?
    if 'related_entities' in res and res['related_entities']:
        print("   Graph Insights:")
        for ent in res['related_entities'][:3]:
            print(f"      - {ent.get('text', 'Entity')} ({ent.get('type', 'Unknown')})")
    print("")

87. 生命周期管理

生产系统需要维护。你可以查询历史、检查健康状况并修剪旧数据。

对话历史

# 获取最近的聊天历史以用于上下文窗口
history = context.conversation(
    conversation_id=session_id,
    limit=5
)

print(f"Chat History for {session_id}:")
for msg in history:
    print(f" - {msg['content']}")

系统健康与统计

# 获取系统健康与统计信息
stats = context.stats()
print("System Vital Signs:")
print(f"   - Total Memories: {stats.get('total_items', 0)}")
print(f"   - Graph Nodes:    {stats.get('graph_stats', {}).get('node_count', 'N/A')}")
print(f"   - Graph Edges:    {stats.get('graph_stats', {}).get('edge_count', 'N/A')}")

9小结

你已经使用 Semantica 的生产级模块成功构建了一个上下文感知智能体

关键成果: 1. 持久化:换入 FAISS 和 Neo4j 用于真实世界的存储。 2. GraphRAG:演示了图谱关系如何提高检索准确性。 3. 实体注入:手动教会智能体关于业务关系的知识。

这一架构已准备好扩展到数百万个向量和图谱节点。