Microsoft Azure 认知服务
Microsoft Azure 认知服务 API 使用机器学习来查找文本中的见解和关系。本章中的过程充当对该 API 调用的包装器,以从存储为节点属性的文本中提取实体和关键词,并提供情感分析。
每个过程都有两种模式
-
流 - 返回从 API 返回的 JSON 构建的映射
过程概述
下面描述了这些过程
限定名称 | 类型 | 发布 |
---|---|---|
|
|
|
apoc.nlp.azure.entities.stream
|
|
|
apoc.nlp.azure.keyPhrases.graph
|
|
|
apoc.nlp.azure.keyPhrases.stream
|
|
|
apoc.nlp.azure.sentiment.graph
|
|
|
apoc.nlp.azure.sentiment.stream
|
|
|
目前,Microsoft Azure 认知服务 API 支持十多种语言的文本输入。为了获得最佳效果,请确保您的文本是 认知服务支持的语言之一. |
实体提取
实体提取过程 (apoc.nlp.azure.entities.*
) 是 Azure 文本分析 API 的 实体 终结点的包装器。此 API 方法返回给定文档中已知实体和一般命名实体(“人物”、“位置”、“组织”等)的列表。
下面描述了这些过程
签名 |
---|
apoc.nlp.azure.entities.graph(source :: ANY?, config = {} :: MAP?) :: (graph :: MAP?) |
apoc.nlp.azure.entities.stream(source :: ANY?, config = {} :: MAP?) :: (node :: NODE?, value :: MAP?, error :: MAP?) |
此过程支持以下配置参数
名称 | 类型 | 默认值 | 说明 |
---|---|---|---|
key |
字符串 |
空 |
Microsoft.CognitiveServicesTextAnalytics API 密钥 |
url |
字符串 |
空 |
Microsoft.CognitiveServicesTextAnalytics 端点 |
nodeProperty |
字符串 |
text |
提供节点上包含待分析非结构化文本的属性 |
此外,apoc.nlp.azure.entities.graph
支持以下配置参数
名称 | 类型 | 默认值 | 说明 |
---|---|---|---|
scoreCutoff |
双精度 |
0.0 |
实体在图中存在的得分的较低限制。值必须介于 0 和 1 之间。 分数是 Amazon Comprehend 对检测准确性的置信度水平的指标。 |
write |
布尔值 |
false |
持久化实体图 |
writeRelationshipType |
字符串 |
ENTITY |
从源节点到实体节点的关系类型 |
writeRelationshipProperty |
字符串 |
score |
从源节点到实体节点的关系属性 |
CALL apoc.nlp.azure.entities.stream(source:Node or List<Node>, {
key: String,
url: String,
nodeProperty: String
})
YIELD value
CALL apoc.nlp.azure.entities.graph(source:Node or List<Node>, {
key: String,
url: String,
nodeProperty: String,
scoreCutoff: Double,
writeRelationshipType: String,
writeRelationshipProperty: String,
write: Boolean
})
YIELD graph
关键短语
关键短语过程 (apoc.nlp.azure.keyPhrases.*
) 是围绕 关键短语 Azure 文本分析 API 端点的包装器。关键短语是输入文本中的关键谈话要点。
过程如下所述
签名 |
---|
apoc.nlp.azure.keyPhrases.graph(source :: ANY?, config = {} :: MAP?) :: (graph :: MAP?) |
apoc.nlp.azure.keyPhrases.stream(source :: ANY?, config = {} :: MAP?) :: (node :: NODE?, value :: MAP?, error :: MAP?) |
该过程支持以下配置参数
名称 | 类型 | 默认值 | 说明 |
---|---|---|---|
key |
字符串 |
空 |
Microsoft.CognitiveServicesTextAnalytics API 密钥 |
url |
字符串 |
空 |
Microsoft.CognitiveServicesTextAnalytics 端点 |
nodeProperty |
字符串 |
text |
提供节点上包含待分析非结构化文本的属性 |
此外,apoc.nlp.azure.keyPhrases.graph
支持以下配置参数
名称 | 类型 | 默认值 | 说明 |
---|---|---|---|
write |
布尔值 |
false |
持久化关键短语图 |
writeRelationshipType |
字符串 |
KEY_PHRASE |
从源节点到关键短语节点的关系类型 |
CALL apoc.nlp.azure.keyPhrases.stream(source:Node or List<Node>, {
key: String,
url: String,
nodeProperty: String
})
YIELD value
CALL apoc.nlp.azure.keyPhrases.graph(source:Node or List<Node>, {
key: String,
url: String,
nodeProperty: String,
writeRelationshipType: String,
write: Boolean
})
YIELD graph
情感
情感过程 (apoc.nlp.azure.sentiment.*
) 是围绕 情感 Azure 文本分析 API 端点的包装器。该 API 返回介于 0 和 1 之间的数字分数。接近 1 的分数表示积极的情感,而接近 0 的分数表示消极的情感。分数为 0.5 表示缺乏情感(例如,事实陈述)。
下面描述了这些过程
签名 |
---|
apoc.nlp.azure.sentiment.graph(source :: ANY?, config = {} :: MAP?) :: (graph :: MAP?) |
apoc.nlp.azure.sentiment.stream(source :: ANY?, config = {} :: MAP?) :: (node :: NODE?, value :: MAP?, error :: MAP?) |
该过程支持以下配置参数
名称 | 类型 | 默认值 | 说明 |
---|---|---|---|
key |
字符串 |
空 |
Microsoft.CognitiveServicesTextAnalytics API 密钥 |
url |
字符串 |
空 |
Microsoft.CognitiveServicesTextAnalytics 端点 |
nodeProperty |
字符串 |
text |
提供节点上包含待分析非结构化文本的属性 |
此外,apoc.nlp.azure.sentiment.graph
支持以下配置参数
名称 | 类型 | 默认值 | 说明 |
---|---|---|---|
write |
布尔值 |
false |
持久化情感图 |
CALL apoc.nlp.azure.sentiment.stream(source:Node or List<Node>, {
key: String,
url: String,
nodeProperty: String
})
YIELD value
CALL apoc.nlp.azure.sentiment.graph(source:Node or List<Node>, {
key: String,
url: String,
nodeProperty: String,
write: Boolean
})
YIELD graph
安装依赖项
NLP 过程依赖于 Kotlin 和客户端库,这些库未包含在 APOC 扩展库中。
这些依赖项包含在 apoc-nlp-dependencies-5.21.0-all.jar 中,可以从 发布页面 下载。下载该文件后,应将其放置在 plugins
目录中,并重新启动 Neo4j 服务器。
设置 API 密钥和 URL
我们可以按照 快速入门:使用文本分析客户端库 文章中的说明生成 API 密钥和 URL。完成此操作后,我们应该能够看到一个页面列出我们的凭据,类似于下面的屏幕截图

在本例中,我们的 API URL 是 https://neo4j-nlp-text-analytics.cognitiveservices.azure.com/
,我们可以使用任何隐藏的密钥。
让我们填充并执行以下命令以创建包含这些详细信息的参数。
apiKey
和 apiSecret
参数:param apiKey => ("<api-key-here>");
:param apiUrl => ("<api-url-here>");
或者,我们可以将这些凭据添加到 apoc.conf
中,并使用静态值存储函数检索它们。参见 静态值存储
apoc.static.azure.apiKey=<api-key-here>
apoc.static.azure.apiUrl=<api-url-here>
apoc.conf
中检索 AWS 凭据RETURN apoc.static.getAll("azure") AS azure;
azure |
---|
{apiKey: "<api-key-here>", apiUrl: "<api-url-here>"} |
示例
本节中的示例基于以下示例图
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.azure.entities.stream(a, {
key: $apiKey,
url: $apiUrl,
nodeProperty: "body"
})
YIELD value
UNWIND value.entities AS entity
RETURN entity;
entity |
---|
{name: "Nintendo Switch", wikipediaId: "Nintendo Switch", type: "Other", matches: [{length: 15, text: "Nintendo Switch", wikipediaScore: 0.8339868065025469, offset: 56}], bingId: "b3d617ef-81fc-4188-9a2b-a5cf1f8534b5", wikipediaLanguage: "en", wikipediaUrl: "https://en.wikipedia.org/wiki/Nintendo_Switch"} |
{name: "Nintendo Switch", type: "Organization", matches: [{length: 15, entityTypeScore: 0.94, text: "Nintendo Switch", offset: 56}]} |
{name: "Oberon Media", wikipediaId: "Oberon Media", type: "Organization", matches: [{length: 6, text: "I play", wikipediaScore: 0.032446316016667254, offset: 76}], bingId: "166f6e0f-33b7-8707-bb8b-5a932c498333", wikipediaLanguage: "en", wikipediaUrl: "https://en.wikipedia.org/wiki/Oberon_Media"} |
{name: "a week", subType: "Duration", type: "DateTime", matches: [{length: 6, entityTypeScore: 0.8, text: "a week", offset: 166}]} |
{name: "Mario Kart 8", wikipediaId: "Mario Kart 8", type: "Other", matches: [{length: 12, text: "Mario Kart 8", wikipediaScore: 0.7802000593632747, offset: 205}], bingId: "ce6f55ec-d3d7-032a-0bf8-15ad3e8df3f4", wikipediaLanguage: "en", wikipediaUrl: "https://en.wikipedia.org/wiki/Mario_Kart_8"} |
{name: "Mario Kart", type: "Organization", matches: [{length: 10, entityTypeScore: 0.72, text: "Mario Kart", offset: 205}]} |
{name: "8", subType: "Number", type: "Quantity", matches: [{length: 1, entityTypeScore: 0.8, text: "8", offset: 216}]} |
{name: "Neo4j", wikipediaId: "Neo4j", type: "Other", matches: [{length: 5, text: "Neo4j", wikipediaScore: 0.8150388253887939, offset: 242}], bingId: "bc2f436b-8edd-6ba6-b2d3-69901348d653", wikipediaLanguage: "en", wikipediaUrl: "https://en.wikipedia.org/wiki/Neo4j"} |
{name: "Europe", wikipediaId: "Europe", type: "Location", matches: [{length: 8, text: "European", wikipediaScore: 0.00591759926701263, offset: 248}], bingId: "501457aa-5b70-cfba-cfd8-be882b4bac1e", wikipediaLanguage: "en", wikipediaUrl: "https://en.wikipedia.org/wiki/Europe"} |
我们得到了 9 个不同的实体,尽管我们可以看到其中一些实体指的是同一个东西,但它们的 type
值不同。然后,我们可以应用一个 Cypher 语句,为每个实体创建一个节点,并从这些节点中的每一个节点到 Article
节点创建一个 ENTITY
关系。
MATCH (a:Article {uri: "https://neo4j.ac.cn/blog/pokegraph-gotta-graph-em-all/"})
CALL apoc.nlp.azure.entities.stream(a, {
key: $apiKey,
url: $apiUrl,
nodeProperty: "body"
})
YIELD value
UNWIND value.entities AS entity
WITH a, entity.name AS entity, collect(entity.type) AS types
MERGE (e:Entity {name: entity})
SET e.type = types
MERGE (a)-[:ENTITY]->(e);
或者,我们可以使用图模式自动创建实体图。除了 Entity
标签之外,每个实体节点还将根据 type
属性的值拥有另一个标签。默认情况下,将返回一个虚拟图。
MATCH (a:Article)
WITH collect(a) AS articles
CALL apoc.nlp.azure.entities.graph(articles, {
key: $apiKey,
url: $apiUrl,
nodeProperty: "body",
writeRelationshipType: "ENTITY"
})
YIELD graph AS g
RETURN g
我们可以在 Pokemon 和 Nintendo Switch 实体图 中看到虚拟图的 Neo4j 浏览器可视化效果。
在此可视化效果中,我们还可以看到每个实体节点的分数。此分数表示 API 对实体检测的置信度水平。我们可以使用 scoreCutoff
属性指定分数的最小截止值。
MATCH (a:Article)
WITH collect(a) AS articles
CALL apoc.nlp.azure.entities.graph(articles, {
key: $apiKey,
url: $apiUrl,
nodeProperty: "body",
scoreCutoff: 0.7,
writeRelationshipType: "ENTITY"
})
YIELD graph AS g
RETURN g
我们可以在 置信度 >= 0.7 的 Pokemon 和 Nintendo Switch 实体图 中看到虚拟图的 Neo4j 浏览器可视化效果。
如果我们对该图感到满意并希望将其持久化到 Neo4j 中,我们可以通过指定 write: true
配置来完成此操作。
HAS_ENTITY
关系MATCH (a:Article)
WITH collect(a) AS articles
CALL apoc.nlp.azure.entities.graph(articles, {
key: $apiKey,
url: $apiUrl,
nodeProperty: "body",
scoreCutoff: 0.7,
writeRelationshipType: "HAS_ENTITY",
writeRelationshipProperty: "azureEntityScore",
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.azureEntityScore}] AS entities;
article | entities |
---|---|
"https://neo4j.ac.cn/blog/pokegraph-gotta-graph-em-all/" |
[{score: 0.72, text: "Mario Kart"}, {score: 0.7802000593632747, text: "Mario Kart 8"}, {score: 0.8, text: "8"}, {score: 0.8, text: "a week"}, {score: 0.94, text: "Nintendo Switch"}, {score: 0.8150388253887939, text: "Neo4j"}] |
"https://en.wikipedia.org/wiki/Nintendo_Switch" |
[{score: 0.9023679924293266, text: "Joy-Con"}, {score: 0.98, text: "Nintendo"}, {score: 0.8, text: "March 3, 2017"}, {score: 0.9355623498560008, text: "Nintendo Switch"}, {score: 0.92, text: "Mario Kart"}, {score: 0.8, text: "8"}, {score: 0.8863202650046607, text: "Mario Kart 8"}, {score: 0.8, text: "October 20, 2016"}] |
关键短语
现在让我们从 Article 节点中提取关键短语。我们要分析的文本存储在节点的 body
属性中,因此我们需要通过 nodeProperty
配置参数指定它。
MATCH (a:Article {uri: "https://neo4j.ac.cn/blog/pokegraph-gotta-graph-em-all/"})
CALL apoc.nlp.azure.keyPhrases.stream(a, {
key: $apiKey,
url: $apiUrl,
nodeProperty: "body"
})
YIELD value
UNWIND value.keyPhrases AS keyPhrase
RETURN keyPhrase;
keyPhrase |
---|
"board games" |
"card games" |
"tournaments" |
"role" |
"organised lunch-time Mario Kart" |
"Neo4j European offices" |
"Nintendo Switch" |
"friends" |
"feet" |
"days" |
或者,我们可以使用图模式自动创建关键短语图。将为提取的每个关键短语创建一个带有 KeyPhrase
标签的节点。
默认情况下,将返回一个虚拟图,但可以通过指定 write: true
配置来持久化该图。
MATCH (a:Article {uri: "https://neo4j.ac.cn/blog/pokegraph-gotta-graph-em-all/"})
CALL apoc.nlp.azure.keyPhrases.graph(a, {
key: $apiKey,
url: $apiUrl,
nodeProperty: "body",
writeRelationshipType: "KEY_PHRASE",
write: true
})
YIELD graph AS g
RETURN g;
我们可以在 Pokemon 关键短语图 中看到虚拟图的 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/" |
["card games", "board games", "friends", "feet", "Nintendo Switch", "days", "organised lunch-time Mario Kart", "tournaments", "Neo4j European offices", "role"] |
情感
现在让我们提取 Article 节点的情感。我们要分析的文本存储在节点的 body
属性中,因此我们需要通过 nodeProperty
配置参数指定它。
MATCH (a:Article {uri: "https://neo4j.ac.cn/blog/pokegraph-gotta-graph-em-all/"})
CALL apoc.nlp.azure.sentiment.stream(a, {
key: $apiKey,
url: $apiUrl,
nodeProperty: "body"
})
YIELD value
RETURN value;
value |
---|
{score: 0.5, id: "0"} |
或者,我们可以使用图模式自动存储情感及其得分。
默认情况下,将返回一个虚拟图,但可以通过指定 write: true
配置来持久化该图。情感得分存储在 sentimentScore
属性中。
MATCH (a:Article {uri: "https://neo4j.ac.cn/blog/pokegraph-gotta-graph-em-all/"})
CALL apoc.nlp.azure.sentiment.graph(a, {
key: $apiKey,
url: $apiUrl,
nodeProperty: "body",
write: true
})
YIELD graph AS g
UNWIND g.nodes AS node
RETURN node {.uri, .sentimentScore} AS node;
node |
---|
{uri: "https://neo4j.ac.cn/blog/pokegraph-gotta-graph-em-all/", sentimentScore: 0.5} |