面向客户与零售分析的GraphRAG代理

这是一个端到端的工作示例,用于构建GraphRAG代理以加速客户和零售分析。它涵盖了整个过程,从:

  1. 快速从混合的非结构化和结构化数据源构建图谱

  2. 在此过程中解析和链接图谱中的实体

  3. 创建多样化的图谱检索工具,包括查询模板、向量搜索、动态text2Cypher和图谱社区检测,以回答更广泛的问题

  4. 使用Semantic Kernel构建代理,用于执行分析和响应复杂的用户问题

所有这些都使用一个中心的事实来源图谱Schema来管理流程和AI交互,确保更高的数据和检索质量。

此工作流程可适用于各种其他业务领域的分析、报告和问答——特别是当:

  • 数据源包含结构化和非结构化数据的混合。

  • AI需要导航一个非简单的业务领域模型以获得准确的响应。

  • 用例需要灵活性和扩展到复杂、不断演进的AI驱动任务的能力。

请按照以下说明自行尝试!🚀

ai customer graph query sample

先决条件

  1. Python >= 3.8

  2. OpenAI API 密钥

设置

克隆 GitHub 仓库。

git clone https://github.com/neo4j-product-examples/graphrag-examples.git

创建并激活一个新的Python虚拟环境。

python -m venv graphrag_venv
source graphrag_venv/bin/activate

切换到项目目录并安装依赖项。

cd graphrag-examples
pip install -r requirements.txt

根据此处的指示创建一个 Neo4j DB 实例。

切换到 `customer-graph` 目录并通过复制 `.env.template` 创建 `.env` 文件

cd customer-graph
cp .env.template .env

将 Neo4j 凭据和 OpenAI 密钥替换为您自己的。

从源数据创建图谱

创建图谱需要摄入非结构化和结构化数据。您将使用 `ontos` 文件夹中的Schema来驱动它们。有关这些Schema如何从中心源生成的更多信息,请参阅Schema生成部分。

源数据是H&M个性化时尚推荐数据集的样本,它包含真实客户的购买数据,其中包含丰富的关于产品的信息,包括名称、类型、描述。我们使用ChatGPT进一步增强了这些数据——模拟了不同商品的供应商和退货/退款的贷记单。 `data` 文件夹包含结果的结构化数据(CSV格式)和非结构化数据,形式为 `credit-notes.pdf`,其中包含退货/退款数据。

注意:请按以下顺序执行步骤,顺序颠倒可能会导致一些重复数据删除和索引问题。

1) 加载非结构化数据

运行非结构化数据摄入。这将需要几分钟。

python unstuctured_ingest.py

此脚本对 `credit-notes.pdf` 文件执行实体提取,并根据客户Schema将实体和关系写入图谱。

完成后,您可以检查数据库以查看生成的图谱。转到Aura控制台并导航到“查询”选项卡。

ai customer graph unstruct ingest 1 goto query

选择“连接实例”按钮

ai customer graph unstruct ingest 2 query

系统将提示您选择您的Aura实例。选择您为此项目创建的实例并输入您的凭据

ai customer graph unstruct ingest 3 connect

进入查询选项卡后,您应该在侧边栏中看到包含CreditNode、Order、Article、Document和Chunk的节点和关系。

ai customer graph unstruct ingest 4 graph stats

运行以下简单的Cypher查询以查看数据样本并进行探索。

MATCH p=()--() RETURN p LIMIT 1000

您应该看到订单、贷记单和商品之间清晰的关系,以及它们与源块(即文档文本块)以及包含元数据的单个文档节点的连接。

ai customer graph unstruct ingest 5 simple query

2) 合并结构化数据

我们将使用 Aura Importer,它允许您将CSV或其他关系数据库中的结构化数据映射到图谱。

前往Aura控制台,导航到“导入”选项卡

ai customer graph struct ingest 0 goto import

选择左上角的省略号,然后从下拉菜单中选择“打开模型”

ai customer graph struct ingest 1 open model

选择 `ontos` 文件夹中的 `customer-struct-import.json`。生成的数据模型应如下所示

ai customer graph struct ingest 2 see model

现在您需要选择数据源。Aura Import 允许您从多种类型的数据库导入数据,但今天我们将使用本地 CSV 文件。在“数据源”面板顶部选择“浏览”。

ai customer graph struct ingest 3 get sources

选择 `data` 目录中的所有 CSV 文件。完成后,您应该在每个节点和关系上看到绿色的勾号。选择一个节点时,您还应该看到节点属性和 CSV 文件中列之间的映射。

ai customer graph struct ingest 5 see mapping

我们现在准备运行导入。选择屏幕左上角的蓝色“运行导入”按钮。系统将提示您选择您的Aura实例——选择您为此项目创建的实例并输入您的凭据

ai customer graph struct ingest 6 connection credentials

导入只需几秒钟。完成后,您应该会看到一个“导入结果”弹出窗口,其中包含“成功完成”消息和一些统计信息。

ai customer graph struct ingest 7 import results

3) 后处理脚本

后处理脚本负责创建文本属性、嵌入和向量索引,以支持产品节点的搜索。由于我们需要分批调用OpenAI嵌入端点以检索文本嵌入,因此运行需要几分钟。

python ingest_post_processing.py

完成后,返回 Aura 控制台中的查询选项卡,运行一个简单的查询来抽样图谱,如下所示

MATCH p=()--() RETURN p LIMIT 1000
ai customer graph confirm ingest

您现在应该能看到非结构化数据、结构化数据以及产品文本/向量属性合并到一张图谱中!

运行代理

目前,运行代理的最佳方式是通过命令行工具 `cli_agent.py`。streamlit 应用程序 `app.py` 仍在开发中,并且在多轮问答对话中仍存在挂起问题。

要运行,请导航到 `graphrag` 文件夹并运行文件

cd graphrag
python cli_agent.py

一些可以尝试的示例问题:

  • 春天有什么好的毛衣吗?不要太保暖的!

  • 哪些供应商的退货(即贷记单)数量最多?

  • 供应商1616退货最多的3种产品是什么?获取这些产品代码,并找到其他退货较少的供应商,我可以用他们来替代。

  • 您能进行客户细分分析吗?

  • 每个细分市场最常见的购买产品类型是什么?

  • 您能进行客户细分分析吗?对于最大的群体,为他们制定一个富有创意的春季促销活动,突出推荐产品。以电子邮件形式起草。

⚠️ 注意:代理AI仍是一项不断发展的技术,可能并非总是按预期开箱即用。例如,代理可能会选择与预期不同的工具,导致错误或不良响应。本项目提供了一个最小的代理示例,重点关注GraphRAG的增强和集成,而不是构建一个完全健壮的代理系统。要使用Semantic Kernel为代理行为增加更多稳定性和规范化,请参阅其文档。对于在类似数据集上使用确定性工具和检索查询(而非代理)的GraphRAG示例,请参阅面向客户体验的GraphRAG^

Schema生成

单源图谱Schema是 `ontos` 目录中的 `customer.ttl`。它是在webprotege中构建并以turtle (ttl) 格式导出的。 `ontos` 目录中的其他Schema只是它的派生,并将在下面更详细地描述。

根据 GoingMeta 系列S2 第5集中描述的过程,此Schema被转换为JSON格式以上传到 Aura Import。其源代码位于此处。该Schema在 Aura Import 中进行了调整,以生成用于结构化数据摄入的 `customer-struct-import.json`。这些调整包括添加CSV属性映射和排除结构化数据摄入中不需要的一些节点。

非结构化数据摄入(`unstructured_ingest.py`)直接使用源 TTL Schema 来指导实体提取和图写入过程。如果您查看 `customer.ttl` 文件,您会看到一些类和属性的“注释”注解。这些注解被传递给 LLM,以更好地描述数据 Schema 并提高实体提取的数据质量。

`ontos` 目录中的最终Schema是 `text-to-cypher.json`,它被 graphrag 应用程序用于 text2Cypher 查询生成——特别是在 `graphrag/retail_service.py` 中。它是通过对数据库运行以下查询生成的

CALL apoc.meta.stats() YIELD relTypes
WITH  KEYS(relTypes) as relTypes
UNWIND relTypes as rel
WITH rel, split(split(rel, '[:')[1],']') as relationship
WITH rel, relationship[0] as relationship
CALL apoc.cypher.run("MATCH p = " + rel + " RETURN p LIMIT 10", {})
YIELD value
WITH relationship as relationshipType, nodes(value.p) as nodes, apoc.any.properties(nodes(value.p)[0]) as startNodeProps, apoc.any.properties(nodes(value.p)[-1]) as endNodeProps
WITH DISTINCT labels(nodes[0]) as startNodeLabels, relationshipType, labels(nodes[-1]) as endNodeLabels,  KEYS(startNodeProps) as startNodeProps,  KEYS(endNodeProps) as endNodeProps
WITH startNodeLabels, relationshipType, endNodeLabels, COLLECT(endNodeProps) as endNodeProps, COLLECT(startNodeProps) as startNodeProps
WITH startNodeLabels, relationshipType, endNodeLabels, apoc.coll.toSet(apoc.coll.flatten(endNodeProps)) as endNodeProps, apoc.coll.toSet(apoc.coll.flatten(startNodeProps)) as startNodeProps
RETURN COLLECT({source:{label:startNodeLabels , properties:startNodeProps}, relationship:relationshipType, target:{label:endNodeLabels , properties:endNodeProps}}) as schema
© . All rights reserved.