用 Bedrock、Neptune 和个性化 PageRank 搭建 HippoRAG

2026-07-02 25 预计阅读时间: 1 分钟
来源: aws.amazon.com AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:9 分钟

传统 RAG 常把知识切成文本块,再用向量相似度召回。HippoRAG 的关键变化是:把知识组织成图,让检索过程不只看“这段文字像不像问题”,还看实体之间如何连接、哪些节点在当前问题语境下更重要。基于 AWS 的实现路径很清晰:Amazon Bedrock 提供 LLM 能力,Amazon Titan Embeddings 生成向量表示,Amazon Neptune 存图,Amazon Neptune Analytics 运行 Personalized PageRank 这类图算法。

为什么 HippoRAG 不只是“向量库换成图数据库”

向量检索擅长找到语义相近的段落,但企业知识往往不是孤立段落:客户、合同、产品、故障、负责人、时间线之间有明确关系。HippoRAG 的思路更接近“先激活相关记忆,再沿关系扩散”:

  • 文档被解析成实体、关系和证据文本。
  • 实体和关系进入 Neptune 图数据库。
  • 文本块或实体说明通过 Titan Embeddings 生成向量。
  • 查询时先用 embedding 找到种子节点,再用 Personalized PageRank 在图上扩散。
  • 最终把排名靠前的节点、边和证据文本交给 Bedrock 上的 LLM 生成答案。

这类方法的价值在多跳问题里更明显。例如“某客户使用的产品最近一次故障是否影响了同一地区的其他客户”,答案通常分散在工单、客户档案、产品拓扑和地区信息中,单纯向量召回容易漏掉中间关系。

一条企业级链路:Bedrock 负责语言,Neptune 负责关系

可以把系统拆成四层:

  1. 摄取层:从文档、Wiki、工单、CRM 中抽取实体、关系和证据文本。
  2. 表示层:用 Amazon Titan Embeddings 给查询、实体描述或文本片段生成向量。
  3. 图层:用 Amazon Neptune 保存节点和边,例如 Customer -> USES -> ProductIncident -> AFFECTS -> Region
  4. 推理层:用 Neptune Analytics 执行 Personalized PageRank,选择最有解释力的子图,再调用 Amazon Bedrock 生成回答。

关键不是把所有内容都塞进 prompt,而是让图算法先做一次“注意力筛选”。Personalized PageRank 的个性化种子可以来自查询向量召回结果:哪些实体最像当前问题,就从哪些实体开始在图上扩散。

可以这样实践:最小化查询工作流

下面示例演示一个可改造的 Python 查询流程:调用 Titan Embeddings 生成查询向量,假设你已有一个向量检索函数返回 Neptune 节点 ID,再把这些节点作为 Personalized PageRank 的种子,最后把检索结果交给 Bedrock 模型。示例里的 run_pprfetch_evidence 需要替换成你们实际的 Neptune Analytics / Neptune 查询封装。

运行前需要修改:AWS_REGIONGRAPH_ID、模型 ID,以及 Neptune 查询函数实现。

import json
import boto3

AWS_REGION = "us-east-1"
TITAN_EMBED_MODEL = "amazon.titan-embed-text-v2:0"
LLM_MODEL = "anthropic.claude-3-sonnet-20240229-v1:0"

bedrock = boto3.client("bedrock-runtime", region_name=AWS_REGION)


def embed_text(text: str) -> list[float]:
    response = bedrock.invoke_model(
        modelId=TITAN_EMBED_MODEL,
        body=json.dumps({"inputText": text}),
    )
    payload = json.loads(response["body"].read())
    return payload["embedding"]


def vector_search_nodes(query_embedding: list[float], limit: int = 5) -> list[str]:
    # 可以替换为 OpenSearch、Neptune 向量索引或你自己的 ANN 服务。
    # 返回与问题最相关的图节点 ID,作为 Personalized PageRank 的种子。
    return ["customer:acme", "product:payment-api", "incident:2024-017"][:limit]


def run_ppr(seed_node_ids: list[str], top_k: int = 20) -> list[str]:
    # 可以替换为 Neptune Analytics 的 Personalized PageRank 调用。
    # 输出按重要性排序的节点 ID。
    return seed_node_ids + ["region:ap-southeast-1", "team:sre-payments"]


def fetch_evidence(node_ids: list[str]) -> str:
    # 可以用 Gremlin/SPARQL/openCypher 从 Neptune 取节点、边和证据文本。
    return """
- customer:acme USES product:payment-api
- incident:2024-017 AFFECTS product:payment-api
- incident:2024-017 OCCURRED_IN region:ap-southeast-1
- team:sre-payments OWNS product:payment-api
""".strip()


def answer(question: str) -> str:
    query_embedding = embed_text(question)
    seeds = vector_search_nodes(query_embedding)
    ranked_nodes = run_ppr(seeds)
    context = fetch_evidence(ranked_nodes)

    prompt = f"""基于下面的图证据回答问题。只使用证据中的事实;如果证据不足,请说明缺口。

问题:{question}

图证据:
{context}
"""

    response = bedrock.invoke_model(
        modelId=LLM_MODEL,
        body=json.dumps({
            "anthropic_version": "bedrock-2023-05-31",
            "max_tokens": 600,
            "messages": [{"role": "user", "content": prompt}],
        }),
    )
    payload = json.loads(response["body"].read())
    return payload["content"][0]["text"]


if __name__ == "__main__":
    print(answer("ACME 使用的支付 API 最近故障影响了哪些区域,应该找哪个团队?"))

如果要把这段流程放进服务里,可以把 vector_search_nodesrun_pprfetch_evidence 做成三个可观测步骤,分别记录召回节点、PageRank 分数和最终证据。这样排查幻觉时,不会只看到一个 LLM 输出,而能看到它到底“看见了哪张子图”。

图建模会决定答案质量

HippoRAG 的效果很大程度取决于图怎么建。不要只抽取“名词 A 关联名词 B”这种松散边;企业场景更需要有类型、有方向、有证据的关系:

(:Customer {id: "customer:acme", name: "ACME"})
(:Product {id: "product:payment-api", name: "Payment API"})
(:Incident {id: "incident:2024-017", severity: "high"})

(:Customer)-[:USES {source: "crm", confidence: 0.93}]->(:Product)
(:Incident)-[:AFFECTS {source: "ticket", confidence: 0.88}]->(:Product)

实践中建议给每条边保留 sourcetimestampconfidence。原因很简单:LLM 生成答案时需要证据;运维排障时需要追溯;图算法扩散时也需要过滤低置信度或过期关系。

落地时别忽略这些边界

  • 成本边界:Embedding、图算法和 LLM 调用都要计费,生产环境应缓存查询向量和高频子图。
  • 延迟边界:Personalized PageRank 适合做高质量扩展,但需要控制图规模、跳数和 top-k。
  • 权限边界:企业图里常有敏感客户、合同和人员信息,检索阶段就要做权限裁剪,不能等到 prompt 阶段再过滤。
  • 评估边界:不要只评估最终答案,还要评估种子召回、PPR 排名、证据覆盖率和引用正确性。

如果你的知识库主要是 FAQ,普通向量 RAG 可能已经足够;如果问题经常跨系统、跨实体、跨时间线,HippoRAG 这类“向量 + 图 + 个性化排序”的架构就值得投入。一个稳妥的采用路线是:先选一个多跳问题密集的业务域,建小图,记录 PageRank 前后的召回差异,再决定是否扩展到全企业知识图谱。


相关推荐