Amazon Web Services (AWS)
Amazon Web Services (AWS) Comprehend 自然语言 API 使用机器学习来查找文本中的见解和关系。本章中的过程充当对该 API 调用的包装器,以从存储为节点属性的文本中提取实体和关键短语。
每个过程都有两种模式
-
流 - 返回从 API 返回的 JSON 构建的映射
-
图 - 基于 API 返回的值创建图或虚拟图
本章中描述的过程对调用线程执行 API 调用和随后的数据库更新。如果我们想对 API 发出并行请求并避免在运行写入数据库的过程时,由于在内存中保留太多事务状态而导致的内存不足错误,请参阅 批量请求。 |
过程概述
下面描述了这些过程
限定名称 | 类型 | 版本 |
---|---|---|
|
|
|
|
|
|
|
|
|
apoc.nlp.aws.keyPhrases.stream
|
|
|
|
|
|
|
|
|
目前,Amazon Comprehend API 支持超过 10 种语言的文本输入。为了获得更好的结果,请确保您的文本是 Amazon Comprehend 支持的语言之一。 |
实体提取
实体提取过程(apoc.nlp.aws.entities.*
)是围绕 Detect Entities 的 AWS Comprehend 自然语言 API 操作的包装器。此 API 方法查找文本中的实体,这些实体被定义为对现实世界对象(例如人、地点和商业物品)的唯一名称的文本引用,以及对度量(例如日期和数量)的精确引用。
下面描述了这些过程
签名 |
---|
apoc.nlp.aws.entities.stream(source :: ANY?, config = {} :: MAP?) :: (node :: NODE?, value :: MAP?, error :: MAP?) |
apoc.nlp.aws.entities.graph(source :: ANY?, config = {} :: MAP?) :: (graph :: MAP?) |
这些过程支持以下配置参数
名称 | 类型 | 默认值 | 描述 |
---|---|---|---|
key |
字符串 |
空 |
AWS 访问控制密钥 |
secret |
字符串 |
空 |
AWS 访问控制密钥 |
nodeProperty |
字符串 |
text |
提供的节点上包含要分析的非结构化文本的属性 |
此外,apoc.nlp.aws.entities.graph
支持以下配置参数
名称 | 类型 | 默认值 | 描述 |
---|---|---|---|
scoreCutoff |
双精度 |
0.0 |
实体在图中存在的评分下限。值必须介于 0 和 1 之间。 评分是 Amazon Comprehend 对检测准确性的置信水平的指标。 |
write |
布尔值 |
false |
持久化实体图 |
writeRelationshipType |
字符串 |
实体 |
从源节点到实体节点的关系类型 |
writeRelationshipProperty |
字符串 |
score |
从源节点到实体节点的关系属性 |
CALL apoc.nlp.aws.entities.stream(source:Node or List<Node>, {
key: String,
secret: String,
nodeProperty: String
})
YIELD value
CALL apoc.nlp.aws.entities.graph(source:Node or List<Node>, {
key: String,
secret: String,
nodeProperty: String,
scoreCutoff: Double,
writeRelationshipType: String,
writeRelationshipProperty: String,
write: Boolean
})
YIELD graph
关键短语
关键短语过程(apoc.nlp.aws.keyPhrases.*
)是围绕 Detect Key Phrases 的 AWS Comprehend 自然语言 API 操作的包装器。关键短语是包含描述特定事物的名词短语的字符串。它通常由一个名词和区分它的修饰语组成。
下面描述了这些过程
签名 |
---|
apoc.nlp.aws.keyPhrases.stream(source :: ANY?, config = {} :: MAP?) :: (node :: NODE?, value :: MAP?, error :: MAP?) |
apoc.nlp.aws.keyPhrases.graph(source :: ANY?, config = {} :: MAP?) :: (graph :: MAP?) |
这些过程支持以下配置参数
名称 | 类型 | 默认值 | 描述 |
---|---|---|---|
key |
字符串 |
空 |
AWS 访问控制密钥 |
secret |
字符串 |
空 |
AWS 访问控制密钥 |
nodeProperty |
字符串 |
text |
提供的节点上包含要分析的非结构化文本的属性 |
此外,apoc.nlp.aws.keyPhrases.graph
支持以下配置参数
名称 | 类型 | 默认值 | 描述 |
---|---|---|---|
scoreCutoff |
双精度 |
0.0 |
实体在图中存在的评分下限。值必须介于 0 和 1 之间。 评分是 Amazon Comprehend 对检测准确性的置信水平的指标。 |
write |
布尔值 |
false |
持久化关键短语图 |
writeRelationshipType |
字符串 |
关键短语 |
从源节点到关键短语节点的关系类型 |
writeRelationshipProperty |
字符串 |
score |
从源节点到关键短语节点的关系属性 |
CALL apoc.nlp.aws.keyPhrases.stream(source:Node or List<Node>, {
key: String,
secret: String,
nodeProperty: String
})
YIELD value
CALL apoc.nlp.aws.keyPhrases.graph(source:Node or List<Node>, {
key: String,
secret: String,
nodeProperty: String,
scoreCutoff: Double,
writeRelationshipType: String,
writeRelationshipProperty: String,
write: Boolean
})
YIELD graph
情感
情感过程(apoc.nlp.aws.sentiment.*
)是围绕 Determine Sentiment 的 AWS Comprehend 自然语言 API 操作的包装器。您可以确定情感是积极的、消极的、中性的还是混合的。
下面描述了这些过程
签名 |
---|
apoc.nlp.aws.sentiment.stream(source :: ANY?, config = {} :: MAP?) :: (node :: NODE?, value :: MAP?, error :: MAP?) |
apoc.nlp.aws.sentiment.graph(source :: ANY?, config = {} :: MAP?) :: (graph :: MAP?) |
这些过程支持以下配置参数
名称 | 类型 | 默认值 | 描述 |
---|---|---|---|
key |
字符串 |
空 |
AWS 访问控制密钥 |
secret |
字符串 |
空 |
AWS 访问控制密钥 |
nodeProperty |
字符串 |
text |
提供的节点上包含要分析的非结构化文本的属性 |
此外,apoc.nlp.aws.sentiment.graph
支持以下配置参数
名称 | 类型 | 默认值 | 描述 |
---|---|---|---|
write |
布尔值 |
false |
持久化情感图 |
CALL apoc.nlp.aws.sentiment.stream(source:Node or List<Node>, {
key: String,
secret: String,
nodeProperty: String
})
YIELD value
CALL apoc.nlp.aws.sentiment.graph(source:Node or List<Node>, {
key: String,
secret: String,
nodeProperty: String,
writeRelationshipType: String,
write: Boolean
})
YIELD graph
安装依赖项
NLP 过程依赖于 Kotlin 和客户端库,这些库未包含在 APOC Extended 库中。
这些依赖项包含在 apoc-nlp-dependencies-5.21.0-all.jar 中,可以从 releases page 下载。下载该文件后,应将其放置在 plugins
目录中,然后重新启动 Neo4j 服务器。
设置 API 密钥和密钥
我们可以按照 docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html 中的说明生成访问密钥和密钥。完成后,我们可以填充并执行以下命令来创建包含这些详细信息的参数。
apiKey
和 apiSecret
参数:param apiKey => ("<api-key-here>");
:param apiSecret => ("<api-secret-here>");
或者,我们可以将这些凭据添加到 apoc.conf
中,并使用静态值存储函数检索它们。请参阅 Static Value Storage。
apoc.static.aws.apiKey=<api-key-here>
apoc.static.aws.apiSecret=<api-secret-here>
apoc.conf
中检索 AWS 凭据RETURN apoc.static.getAll("aws") AS aws;
aws |
---|
{apiKey: "<api-key-here>", apiSecret: "<api-secret-here>"} |
批处理请求
对 AWS API 的批处理请求和结果的处理可以使用 Periodic Iterate 完成。如果我们想对 AWS API 发出并行请求并减少运行写入数据库的过程时内存中保留的交易状态,这种方法非常有用。
AWS Comprehend API 在一个请求中最多处理 25 个文档,因此为了获得最佳性能,我们应该传递大小为该值倍数的列表。请记住,如果我们传递大型列表,这将导致写入数据库时更多的交易状态,并可能导致内存不足异常。 |
CALL apoc.periodic.iterate("
MATCH (n)
WITH collect(n) as total
CALL apoc.coll.partition(total, 25)
YIELD value as nodes
RETURN nodes", "
CALL apoc.nlp.aws.entities.graph(nodes, {
key: $apiKey,
secret: $apiSecret,
nodeProperty: 'body',
writeRelationshipType: 'AWS_ENTITY',
write:true
})
YIELD graph
RETURN distinct 'done'", {
batchSize: 1,
params: { apiKey: $apiKey, apiSecret: $apiSecret }
}
);
示例
本节中的示例基于以下示例图
CREATE (:Article {
uri: "https://neo4j.ac.cn/blog/pokegraph-gotta-graph-em-all/",
body: "These days I’m rarely more than a few feet away from my Nintendo Switch and I play board games, card games and role playing games with friends at least once or twice a week. I’ve even organised lunch-time Mario Kart 8 tournaments between the Neo4j European offices!"
});
CREATE (:Article {
uri: "https://en.wikipedia.org/wiki/Nintendo_Switch",
body: "The Nintendo Switch is a video game console developed by Nintendo, released worldwide in most regions on March 3, 2017. It is a hybrid console that can be used as a home console and portable device. The Nintendo Switch was unveiled on October 20, 2016. Nintendo offers a Joy-Con Wheel, a small steering wheel-like unit that a Joy-Con can slot into, allowing it to be used for racing games such as Mario Kart 8."
});
实体提取
首先从 Article 节点提取实体。我们要分析的文本存储在节点的 body
属性中,因此我们需要通过 nodeProperty
配置参数指定它。
MATCH (a:Article {uri: "https://neo4j.ac.cn/blog/pokegraph-gotta-graph-em-all/"})
CALL apoc.nlp.aws.entities.stream(a, {
key: $apiKey,
secret: $apiSecret,
nodeProperty: "body"
})
YIELD value
UNWIND value.entities AS entity
RETURN entity;
entity |
---|
{score: 0.780032217502594, endOffset: 71, text: "Nintendo Switch", type: "COMMERCIAL_ITEM", beginOffset: 56} |
{score: 0.8155304193496704, endOffset: 151, text: "at least", type: "QUANTITY", beginOffset: 143} |
{score: 0.7507548332214355, endOffset: 156, text: "once", type: "QUANTITY", beginOffset: 152} |
{score: 0.8760746717453003, endOffset: 172, text: "twice a week", type: "QUANTITY", beginOffset: 160} |
{score: 0.9944096803665161, endOffset: 217, text: "Mario Kart 8", type: "TITLE", beginOffset: 205} |
{score: 0.9946564435958862, endOffset: 247, text: "Neo4j", type: "ORGANIZATION", beginOffset: 242} |
{score: 0.6274040937423706, endOffset: 256, text: "European", type: "LOCATION", beginOffset: 248} |
我们得到 7 个不同的实体。然后我们可以应用一个 Cypher 语句,该语句为每个实体创建一个节点,并从这些节点中的每一个返回到 Article
节点创建一个 ENTITY
关系。
MATCH (a:Article {uri: "https://neo4j.ac.cn/blog/pokegraph-gotta-graph-em-all/"})
CALL apoc.nlp.aws.entities.stream(a, {
key: $apiKey,
secret: $apiSecret,
nodeProperty: "body"
})
YIELD value
UNWIND value.entities AS entity
MERGE (e:Entity {name: entity.text})
SET e.type = entity.type
MERGE (a)-[:ENTITY]->(e)
或者,我们可以使用图模式自动创建实体图。除了拥有 Entity
标签外,每个实体节点还将根据 type
属性的值拥有另一个标签。默认情况下,将返回一个虚拟图。
MATCH (a:Article {uri: "https://neo4j.ac.cn/blog/pokegraph-gotta-graph-em-all/"})
CALL apoc.nlp.aws.entities.graph(a, {
key: $apiKey,
secret: $apiSecret,
nodeProperty: "body",
writeRelationshipType: "ENTITY"
})
YIELD graph AS g
RETURN g;
我们可以在 Pokemon entities graph 中看到虚拟图的 Neo4j 浏览器可视化。
我们可以通过将节点列表传递给过程来计算多个节点的实体。
MATCH (a:Article)
WITH collect(a) AS articles
CALL apoc.nlp.aws.entities.graph(articles, {
key: $apiKey,
secret: $apiSecret,
nodeProperty: "body",
writeRelationshipType: "ENTITY"
})
YIELD graph AS g
RETURN g
我们可以在 Pokemon and Nintendo Switch entities graph 中看到虚拟图的 Neo4j 浏览器可视化。
在此可视化中,我们还可以看到每个实体节点的评分。此评分表示 API 对其检测实体的置信水平。我们可以使用 scoreCutoff
属性指定评分的最小截止值。
MATCH (a:Article)
WITH collect(a) AS articles
CALL apoc.nlp.aws.entities.graph(articles, {
key: $apiKey,
secret: $apiSecret,
nodeProperty: "body",
scoreCutoff: 0.7,
writeRelationshipType: "ENTITY"
})
YIELD graph AS g
RETURN g
我们可以在 Pokemon and Nintendo Switch entities graph with confidence >= 0.7 中看到虚拟图的 Neo4j 浏览器可视化。
如果我们对该图感到满意并希望将其持久化到 Neo4j 中,我们可以通过指定 write: true
配置来实现。
HAS_ENTITY
关系MATCH (a:Article)
WITH collect(a) AS articles
CALL apoc.nlp.aws.entities.graph(articles, {
key: $apiKey,
secret: $apiSecret,
nodeProperty: "body",
scoreCutoff: 0.7,
writeRelationshipType: "HAS_ENTITY",
writeRelationshipProperty: "awsEntityScore",
write: true
})
YIELD graph AS g
RETURN g;
然后我们可以编写一个查询来返回已创建的实体。
MATCH (article:Article)
RETURN article.uri AS article,
[(article)-[r:HAS_ENTITY]->(e:Entity) | {text: e.text, score: r.awsEntityScore}] AS entities;
article | entities |
---|---|
"https://neo4j.ac.cn/blog/pokegraph-gotta-graph-em-all/" |
[{score: 0.9944096803665161, text: "Mario Kart 8"}, {score: 0.8760746717453003, text: "twice a week"}, {score: 0.9946564435958862, text: "Neo4j"}, {score: 0.7507548332214355, text: "once"}, {score: 0.8155304193496704, text: "at least"}, {score: 0.780032217502594, text: "Nintendo Switch"}] |
"https://en.wikipedia.org/wiki/Nintendo_Switch" |
[{score: 0.9990180134773254, text: "Mario Kart 8"}, {score: 0.9997879862785339, text: "March 3, 2017"}, {score: 0.9958534240722656, text: "Nintendo"}, {score: 0.9998348355293274, text: "October 20, 2016"}, {score: 0.753325343132019, text: "Nintendo Switch"}] |
关键短语
现在从 Article 节点提取关键短语。我们要分析的文本存储在节点的 body
属性中,因此我们需要通过 nodeProperty
配置参数指定它。
MATCH (a:Article {uri: "https://neo4j.ac.cn/blog/pokegraph-gotta-graph-em-all/"})
CALL apoc.nlp.aws.keyPhrases.stream(a, {
key: $apiKey,
secret: $apiSecret,
nodeProperty: "body"
})
YIELD value
UNWIND value.keyPhrases AS keyPhrase
RETURN keyPhrase;
keyPhrase |
---|
{score: 0.9999966621398926, endOffset: 10, text: "These days", beginOffset: 0} |
{score: 0.9867414236068726, endOffset: 42, text: "more than a few feet", beginOffset: 22} |
{score: 0.9999999403953552, endOffset: 71, text: "my Nintendo Switch", beginOffset: 53} |
{score: 0.9999997019767761, endOffset: 94, text: "board games", beginOffset: 83} |
{score: 0.9999964237213135, endOffset: 106, text: "card games", beginOffset: 96} |
{score: 0.9998161792755127, endOffset: 129, text: "role playing games", beginOffset: 111} |
{score: 1.0, endOffset: 142, text: "friends", beginOffset: 135} |
{score: 0.8642383217811584, endOffset: 172, text: "a week", beginOffset: 166} |
{score: 0.9999430179595947, endOffset: 215, text: "lunch-time Mario Kart", beginOffset: 194} |
{score: 0.9983567595481873, endOffset: 229, text: "8 tournaments", beginOffset: 216} |
{score: 0.999997615814209, endOffset: 264, text: "the Neo4j European offices", beginOffset: 238} |
或者,我们可以使用图模式自动创建一个关键短语图。将为提取的每个关键短语创建一个带有 KeyPhrase
标签的节点。
默认情况下,将返回一个虚拟图,但可以通过指定 write: true
配置来持久化该图。
MATCH (a:Article {uri: "https://neo4j.ac.cn/blog/pokegraph-gotta-graph-em-all/"})
CALL apoc.nlp.aws.keyPhrases.graph(a, {
key: $apiKey,
secret: $apiSecret,
nodeProperty: "body",
writeRelationshipType: "KEY_PHRASE",
write: true
})
YIELD graph AS g
RETURN g;
我们可以在 Pokemon key phrases graph 中看到虚拟图的 Neo4j 浏览器可视化。
然后我们可以编写一个查询来返回已创建的关键短语。
MATCH (a:Article {uri: "https://neo4j.ac.cn/blog/pokegraph-gotta-graph-em-all/"})
RETURN a.uri AS article,
[(a)-[:KEY_PHRASE]->(k:KeyPhrase) | k.text] AS keyPhrases;
article | keyPhrases |
---|---|
"https://neo4j.ac.cn/blog/pokegraph-gotta-graph-em-all/" |
["the Neo4j European offices", "a week", "friends", "8 tournaments", "lunch-time Mario Kart", "card games", "board games", "role playing games", "my Nintendo Switch", "more than a few feet", "These days"] |
情感
现在让我们提取文章节点的情感。我们要分析的文本存储在节点的body
属性中,因此我们需要通过nodeProperty
配置参数来指定它。
MATCH (a:Article {uri: "https://neo4j.ac.cn/blog/pokegraph-gotta-graph-em-all/"})
CALL apoc.nlp.aws.sentiment.stream(a, {
key: $apiKey,
secret: $apiSecret,
nodeProperty: "body"
})
YIELD value
RETURN value;
值 |
---|
{index: 0, sentiment: "POSITIVE", sentimentScore: {neutral: 0.33138760924339294, negative: 0.0026062370743602514, mixed: 3.5950531582784606E-6, positive: 0.6660025119781494}} |
或者,我们可以使用图模式自动存储情感及其分数。
默认情况下,会返回一个虚拟图,但可以通过指定write: true
配置来持久化该图。情感存储在sentiment
属性中,该情感的分数存储在sentimentScore
属性中。
MATCH (a:Article {uri: "https://neo4j.ac.cn/blog/pokegraph-gotta-graph-em-all/"})
CALL apoc.nlp.aws.sentiment.graph(a, {
key: $apiKey,
secret: $apiSecret,
nodeProperty: "body",
write: true
})
YIELD graph AS g
UNWIND g.nodes AS node
RETURN node {.uri, .sentiment, .sentimentScore} AS node;
节点 |
---|
{sentiment: "Positive", sentimentScore: 0.6660025119781494, uri: "https://neo4j.ac.cn/blog/pokegraph-gotta-graph-em-all/"} |