图方法在RAG中的应用——现状
检索增强生成(Retrieval-Augmented Generation,简称RAG)结合了大型语言模型(LLM)的自然语言生成能力与信息检索的优势,使响应更加具备上下文感知、准确、相关且富有细微差别。通过将检索纳入生成过程,RAG系统能够保持高度的相关性和事实准确性,使其在知识管理、客户支持和研究等需要精确且上下文适宜的信息的应用中不可或缺。
传统的检索增强生成(RAG)技术在某些场景下虽然有效,但往往难以捕捉现实世界数据中复杂的关系和上下文细微差别。另一方面,知识图谱提供了信息的结构化表示,能够实现更高效的检索和推理。然而,将知识图谱与LLM有效整合以提升RAG性能仍然是一项具有挑战性的任务。
在RAG系统中使用知识图谱越来越被认可,因为它能够改善数据组织和检索精度。基于图的方法现在通常与使用大型语言模型(LLM)从文本语料库中提取和构建复杂关系相关联,这一方法最早由微软在今年早些时候引入[1]。然而,使用LLM构建和维护准确的知识图谱仍然需要大量资源,并面临数据稀疏、重复和需要持续更新等挑战。为了解决这些问题,趋势是使用模块化和层次化的图结构,这些结构能够有效管理大规模数据集。诸如社区检测和摘要等技术正被用于提升基于图的RAG系统的可扩展性和效率。
本文将重点介绍一种我称之为固定实体架构(Fixed Entity Architecture,FEA)的新方法。微软的GraphRAG和FEA这两种方法都解决了知识图谱构建和利用中的常见问题,如可扩展性、复杂性和精度。这些方法代表了将知识图谱与RAG整合的最新进展,利用LLM和高效的图结构技术。它们是两种截然不同的方法,取决于具体的使用案例和数据。这两种方法适用于不同类型的数据和查询,使其在各行各业和研究领域中广泛适用。
相关文章
llm-graph-builder——从非结构化数据创建知识图谱
本文重点
本文提出了一种用于构建知识图谱的新方法,该方法能够为多种使用案例的RAG应用提供更有效的知识库。FEA方法突破了传统基于LLM的图构建方法,旨在解决现有技术的以下局限性:
•在图创建步骤中过度依赖LLM •避免实体重复并消除实体解析的需求 •图的稀疏性
本文结构如下:
•分析GraphRAG和固定实体架构 •GraphRAG —— 微软现有方法概述 •固定实体架构:介绍和比较概述 •本体鱼骨图 •增加知识 •检索过程
我将使用著名的爱因斯坦名言的简单示例来说明这些概念,展示如何构建知识库并执行高级检索。这种方法旨在为您的RAG系统开辟新视野,并展示进一步探索和开发的巨大潜力。
分析GraphRAG和固定实体架构
GraphRAG —— 微软现有方法概述
2024年4月,微软发布了他们的第一篇关于GraphRAG的论文,介绍了一种有趣的方法,利用大型语言模型(LLM)从文本语料库中提取实体和关系,并基于这些实体构建知识图谱。他们将实体聚合成社区,这些社区随后成为其内容的摘要。实际的检索增强生成(RAG)是在这些摘要上进行的,展示了一种在信息检索方面具有显著潜力的方法。
像任何方法一样,GraphRAG有其优缺点。下表1从我的角度突出了微软GraphRAG方法的优点和挑战。需要注意的是,在某些使用案例中,尤其是处理大量文本数据时,预先了解实体之间的关系可能并不总是适用。
在我的案例中,我正在进行一个概念验证(POC),使用的是已知或至少部分已知的本体,并且迫切需要一个RAG实现。任务是基于非常非结构化的数据构建一个高效的知识库。
我最初尝试使用微软的方法在我的数据上构建图,花费了大量时间编写和完善查询,以从文本块中提取实体和关系。在创建了第一个甚至第二个基于LLM生成的图数据库后,我遇到了一个重大问题。信息检索不适合GenAI驱动的应用。数据库中充斥着重复项,实体解析的准确性不足,导致过程耗时且成本高昂。总之,对于我的特定使用案例来说,它太昂贵、太杂乱、太复杂且难以控制。
我意识到,对于我正在处理的定义明确的领域,需要一种不同的方法来在知识图谱上实现RAG——一种快速、主要自动化且不依赖于昂贵的LLM调用的方法。此外,我希望它非常可控和灵活。LLM生成的大量经常重复的实体让我想到,我希望这些实体是固定的,数量更少,并且能够高精度地了解它们是如何连接的。
本文介绍了FEA方法,使用固定实体架构在图上构建RAG。知识图谱是使用Neo4J创建的。
固定实体架构
固定实体架构 —— 新方法介绍
本文提出的固定实体架构(FEA)基于预定义的实体和关系,这些实体和关系构成了您的使用案例领域的本体“鱼骨图”。确定在此结构中包含什么通常是一个深刻的哲学问题,需要广泛的领域知识来开发一个稳健的固定实体架构。或者,您可以考虑知识库的用途,并确定关键或模板文档作为本体鱼骨图的基础。
与微软的方法不同,固定实体架构不依赖于大型语言模型(LLM)来构建图。相反,它利用特定于使用案例的专有领域知识,结合简单的数学技术。这种方法提供了一种高效的方式来解决与基于LLM的方法相关的许多缺点。
比较概述
下表1展示了微软的GraphRAG和固定实体架构两种方法的比较概述。
表1 两种方法的比较概述
总的来说,固定实体架构 适用于定义明确、范围狭窄的领域,特别需要高精度和控制。它具有较低的复杂性、降低的计算成本,并且最小化了对LLM的依赖。然而,它在灵活性方面有所欠缺,在大型数据集上的可扩展性较差,并且需要预先的领域知识。
微软的GraphRAG 在处理大规模、多样化的数据集和复杂查询方面表现出色,提供了跨多个领域的可扩展性和适应性。它支持本地和全局查询,但复杂性更高、资源成本更大,并且对LLM有较强的依赖。当优先考虑简便性、低维护或固定实体时,它的适用性较差。
这里的建议是根据数据集的性质、控制需求和可用资源进行选择。结合两种方法的元素可能会优化性能。
本体鱼骨图
什么是本体?您是否曾考虑过您自己微观世界的本体?在工作中,您每天执行任务,而没有有意识地理解您的大脑如何识别这些“事物”以及如何在它们之间建立连接。试试这个练习:尝试创建一个“事物”的元模型,并绘制它们之间的连接。虽然这听起来具有挑战性,但我有好消息——这是完全可能的,因为您知道自己在做什么!
本体是帮助我们理解周围世界的强大工具。“鱼骨图”隐喻鼓励我们深入探讨定义我们概念领域的基本构建块和连接。创建本体涉及仔细考虑要包含什么、元素之间的关系以及哪些是最重要的。鱼骨结构帮助我们识别核心元素,同时承认将我们的想法带入生活的复杂连接网。
现在,假设您在一个狭窄的领域内工作,并且对构成您工作的实体“鱼骨图”有清晰的理解。您如何轻松地将所有这些信息连接起来,并为任何RAG应用构建一个知识库?继续阅读——我有这些问题的答案。
创建基本的“鱼骨”结构:爱因斯坦示例
在许多组织中,主题专家可以轻松识别定义明确的领域内的关键实体和关系。这些基础知识对于构建有效的知识图谱至关重要。通过利用这些专业知识,可以在几天内建立一个关键实体及其关系的基本“鱼骨图”,为进一步丰富详细信息提供坚实的基础。
在创建鱼骨图时,请记住尽可能为您的实体包含描述。让我们考虑一个著名的示例来说明知识图谱的构建过程:句子“阿尔伯特·爱因斯坦发展了相对论,这彻底改变了理论物理学和天文学。”这个广为人知的句子展示了如何提取实体和关系。下图1展示了基于这个句子的图。
图1 基于句子的图形表示
图1. 句子“阿尔伯特·爱因斯坦发展了相对论,这彻底改变了理论物理学和天文学”的图形表示——固定实体架构图的“鱼骨”本体。
Cypher是一种声明式查询语言,用于与图数据库(尤其是Neo4j)进行交互。它允许用户以直观的类似SQL的语法表达复杂的图模式和关系。Cypher旨在易读,并提供强大的功能,用于查询、更新和管理图数据。它支持模式匹配、过滤和节点及关系的操作,非常适合涉及社交网络、推荐引擎和其他基于图的数据模型的任务。有关更详细的信息,您可以访问官方的Neo4j Cypher文档[2]。
在这里,我假设读者熟悉嵌入、余弦相似度、点积和向量索引等术语。如果不熟悉,请参考额外的文献,如[3–5]。
在我们的爱因斯坦示例中,我们有四个实体(阿尔伯特·爱因斯坦、相对论、理论物理学和天文学)以及三条具有两种类型的边(开发和革命化)。我们可以为每个实体添加简要描述,例如:“阿尔伯特·爱因斯坦是20世纪伟大的物理学家”,等等。将其转换为Cypher代码,创建图的过程如下:
CREATE (a:Entity {label: 'Person' , name: 'Albert Einstein', embeddings: $person_emb}),
(b:Entity {label:'Theory' ,name: 'Theory of relativity', embeddings: $theory_emb}),
(c:Entity {label:'Field', name: 'Theoretical physics', embeddings: $field1_emb }),
(d:Entity {label:'Field', name: 'Astronomy', embeddings: $field2_emb })
// 创建边
CREATE (a)-[:DEVELOPED]->(b),
(b)-[:REVOLUTIONIZED]->(c),
(b)-[:REVOLUTIONIZED]->(d)
请注意,我仅使用一个关联标签“Entity”创建节点,但为每个节点包含不同的标签作为属性。这是为了在后续搜索中保持清晰。所有节点在内部都称为实体,形成了后续操作的固定鱼骨结构。我稍后会添加不同标签的节点,但它们将具有不同的功能——请继续阅读!😉
这种方法的另一个原因是,我尚未找到一种方法能同时为两个或多个节点标签构建统一的索引(如果您知道,请在评论部分告诉我)。
这里的embeddings
参数仅包含“label: name”值,但在实际操作中,我建议还包括实体的详细描述,并将其添加到您的嵌入向量中。
现在,我们有了构建知识库用于RAG应用的“鱼骨图”(图2)。为了创建这个知识库,我们需要文档。对于阿尔伯特·爱因斯坦,我使用了维基百科文章[6]。我使用维基百科API复制了文本,并将其拆分为59个块,每块大小为2000。请注意,在此演示中,我没有优化块的大小;选择的大小是任意的。
图2 Neo4J中的固定实体鱼骨图表示
将文档添加到图中
让我们以以下方式将文档块添加到图中:
prev_node_id = None # 在循环前初始化 prev_node_id
for i, chunk in enumerate(chunks):
# 创建文档节点
query = f'''
CREATE (d:Document {{
chunkID: "{f"chunk_{i}"}",
url: "{url}",
docID: "{document_name}",
full_text: '{escaped_chunk}',
embeddings: {embeddings.embed_documents(chunk).tolist()}}}
)
RETURN ID(d)
'''
run_query(driver, query)
chunk_node_id = result[0]['ID(d)']
# 如果不是第一个块,创建与前一个块的NEXT关系
if prev_node_id is not None:
query = f'''
MATCH (c1:Document), (c2:Document)
WHERE ID(c1) = {prev_node_id} AND ID(c2) = {chunk_node_id}
CREATE (c1)-[:NEXT]->(c2)
CREATE (c2)-[:PREV]->(c1)
'''
run_query(driver, query)
prev_node_id = chunk_node_id
CREATE
(
c2
)-[: PREV ]->(
c1
)
这段代码将块作为标签为“Document”的节点添加(见图3)。
图3 爱因斯坦维基百科文章的前25个块
通过将文档块相互连接为节点,后续检索中将具有显著优势。您可以使用Cypher查询定义,如果找到相似的块,还可以检索前一个和下一个块。就是这么简单!
将文档与固定实体连接
接下来,让我们将文本块连接到我们的固定实体“鱼骨图”。请注意,这种方法不使用任何昂贵的LLM技术,并避免在知识库中创建重复。此外,执行时间仅需毫秒。我们使用一种简单的数学公式,称为点积,它提供了每个块与固定实体之间的余弦相似度值。以下Cypher代码将实现这一点:
MATCH (e:Entity), (d:Document)
WHERE e.embeddings IS NOT NULL
AND d.embeddings IS NOT NULL
AND size(e.embeddings) = size(d.embeddings)
WITH e, d,
reduce(numerator = 0.0, i in range(0, size(e.embeddings)-1) | numerator + toFloat(e.embeddings[i])*toFloat(d.embeddings[i])) as dotProduct,
sqrt(reduce(eSum = 0.0, i in range(0, size(e.embeddings)-1) | eSum + toFloat(e.embeddings[i])^2)) as eNorm,
sqrt(reduce(dSum = 0.0, i in range(0, size(d.embeddings)-1) | dSum + toFloat(d.embeddings[i])^2)) as dNorm
WITH e, d, dotProduct / (eNorm * dNorm) as cosineSimilarity
WHERE cosineSimilarity > 0.8
MERGE (e)-[r:RELATES_TO]->(d)
ON CREATE SET r.cosineSimilarity = cosineSimilarity
RETURN ID(e), e.name, ID(d), d.full_text, r.cosineSimilarity
ORDER BY cosineSimilarity DESC
在此示例中,我们指示数据库使用向量索引从所有实体节点中提取,并通过计算它们与用户查询之间的向量角度来比较它们与每个文档块的相似度。如果余弦相似度超过给定的阈值(此处为0.8),数据库将在实体节点和文档节点之间创建一个名为RELATES_TO
的边。由于块未经过优化,并且固定实体缺乏详细描述,匹配可能不太高。此示例旨在说明该技术。
表2 使用余弦相似度属性自连接的文档节点
图4 通过余弦相似度属性自连接的文档节点结果
图4展示了此查询的结果。一些块自动链接到余弦相似度高于定义阈值0.8的固定实体。您可以根据需要调整此阈值。这种方法允许在检索过程中进一步过滤,仅选择最佳匹配的块。
不仅实体“阿尔伯特·爱因斯坦”连接到了相关的文本块,“相对论”也是如此。随着更多文档的添加,“鱼骨图”实体将越来越多地作为元素之间的连接器。这是使用图的一个优势——几乎所有东西都是相互连接的。没有稀疏性的问题需要聚类。您可以进一步探索这一点,但那将是另一个话题。现在,让我们继续添加更多文档。
请参阅表3,了解理论物理学维基百科文章中的文本如何连接到各种固定实体。
表3 从理论物理学维基百科文章添加的文档与匹配实体的返回结果
表3. 从理论物理学维基百科文章添加的文档与匹配实体的返回结果。
将文档[6–9]附加到我们爱因斯坦句子中的固定实体的结果如图5所示。块被无缝链接到相关实体。
图5 通过余弦相似度属性自连接的文档节点结果
这项技术用于附加文档具有多功能性,适用于各种类型的文档。通过向量化您的数据,您可以轻松地整合和连接所有信息。
Neo4j的优势在于能够在您的图上创建各种类型的索引,更棒的是,您甚至可以使用单个Cypher查询执行混合搜索。让我们为我们的检索准备索引。
创建向量索引
首先,我们创建向量索引:
queries = [ "DROP INDEX test_index_document IF EXISTS;", "DROP INDEX test_index_entity IF EXISTS;" ]
for query in queries:
run_query(driver, query)
# 为文档嵌入创建向量索引
CREATE VECTOR INDEX test_index_document
IF NOT EXISTS
FOR (d:Document)
ON (d.embeddings)
OPTIONS {indexConfig: {
`vector.dimensions`: 768,
`vector.similarity_function`: 'cosine'
}}
# 为实体嵌入创建向量索引
CREATE VECTOR INDEX test_index_entity IF NOT EXISTS
FOR (n:Entity)
ON (n.embeddings)
OPTIONS {indexConfig: {
`vector.dimensions`: 768,
`vector.similarity_function`: 'cosine'
}}
一旦在节点上创建了向量索引,您还可以在边上创建向量索引,如果您有它们的描述。由于此阶段我没有关系的任何文本,因此我将跳过此步骤。
创建文本索引
接下来,我将创建一个文本索引,这也将作为标准关键字索引添加到搜索中。
queries = [ "DROP INDEX text_index_entity IF EXISTS;", "DROP INDEX text_index_document IF EXISTS;", ]
for query in queries:
run_query(driver, query)
# 为实体描述创建全文索引
CREATE FULLTEXT INDEX text_index_entity FOR (n:Entity) ON EACH [n.name]
# 为文档全文文本创建全文索引
CREATE FULLTEXT INDEX text_index_document FOR (d:Document) ON EACH [d.full_text]
现在我们的知识库已准备好进行检索,并可用于构建RAG应用,我们可以开始查询图数据库。
让我们从一个简单的查询开始。我们将要求数据库找到给定查询的最佳匹配答案。例如,我们使用查询:“阿尔伯特·爱因斯坦的研究领域”。
首先,我将使用基于实体的向量索引。查询涉及将原始用户查询嵌入到向量索引中和/或将其用作关键字索引的文本。我将从一个简单的查询(查询1)开始:
CALL db.index.vector.queryNodes('test_index_entity', 10, $user_query)
YIELD node AS vectorNode, score as vectorScore
WITH vectorNode, vectorScore
ORDER BY vectorScore DESC
RETURN vectorNode.name AS label, vectorScore AS score
在这里,我仅查询固定实体,特别是使用建立在它们上的向量索引。结果如下表4所示。
表4 使用查询1的结果
由于我们只有四个实体,结果有些可预测。仅提取实体,尤其是在此阶段缺乏描述时,为RAG应用提供的价值有限。为了增强我们的结果,我们需要提取与问题相关的文档。让我们更进一步,识别与找到的实体最相关的文档(查询2):
CALL db.index.vector.queryNodes('test_index_entity', 10, $user_query)
YIELD node AS vectorNode, score as vectorScore
WITH vectorNode, vectorScore
MATCH (vectorNode)-[r]->(d:Document)
WITH vectorNode.name AS label, vectorScore as score, d.docID as closest_document_name,
d.full_text as closest_document_text, r.cosineSimilarity as similarity
ORDER BY similarity DESC
RETURN label, closest_document_name, closest_document_text, similarity
LIMIT 10
结果,如表5所示,与初始查询略有不同。这里,“天文学”首先返回。然而,而不是预期的“相对论”,出现了“阿尔伯特·爱因斯坦”。使用GraphRAG结合这种方法的优势在于其灵活性:您可以调整搜索以更好地适应应用的需求。让我们完善我们的查询,以优先考虑“天文学”和“相对论”作为此问题的顶级结果。
表5 使用查询2的结果
为了进一步提升结果,我们可以实施一个交叉编码器重新排序步骤。尽管我通常在描述上进行重新排序,但在这种情况下,由于缺乏描述,我将在标签上应用它。我将使用sentence_transformers
库中的cross-encoder/ms-marco-MiniLM-L-6-v2
模型。表6显示了查询2的重新排序结果。
表6 使用查询2包括重新排序的检索信息
如您所见,重新排序与查询结合并未产生预期的结果。为了改进结果,我们可以结合全文或关键字搜索(查询3):
CALL db.index.vector.queryNodes('test_index_entity', 10, $my_query_emb_list)
YIELD node AS vectorNode, score as vectorScore
WITH vectorNode, vectorScore
MATCH (vectorNode)-[r]->(d:Document)
WITH vectorNode.name AS label, vectorScore as score, d.docID as closest_document_name,
d.full_text as closest_document_text, r.cosineSimilarity as similarity
ORDER BY similarity DESC
RETURN label, closest_document_name, closest_document_text, similarity
LIMIT 10
UNION
CALL db.index.fulltext.queryNodes('text_index_entity', $my_query)
YIELD node AS textNode, score as textScore
WITH textNode, textScore
MATCH (textNode)-[r]->(d:Document)
WITH textNode.name AS label, textScore as score, d.docID as closest_document_name,
d.full_text as closest_document_text, r.cosineSimilarity as similarity
ORDER BY similarity DESC
RETURN label, closest_document_name, closest_document_text, similarity
LIMIT 10
这个查询的结果显示在表7中。
表7 使用查询3包括混合向量关键字搜索的检索信息
之前的尝试,包括重新排序,并未产生预期的结果。现在,我将展示检索在图中的真正威力。为了避免APOC库的问题和与Python工具的兼容性问题,我专注于一种清晰、透明的方法。我将使用纯数学方法来说明图的搜索能力的有效性。下一个查询展示了我在工作中称之为“智能搜索”的方法(查询4)。
CALL db.index.vector.queryNodes('test_index_entity', 10, $user_query_emb)
YIELD node AS vectorNode, score as vectorScore
WITH vectorNode, vectorScore
MATCH (vectorNode)-[r]->(d:Document)
WITH DISTINCT vectorNode as e, d, r, r.cosineSimilarity as cosineSimilarity
ORDER BY cosineSimilarity DESC
WITH ID(e) as id, e.label as title,
cosineSimilarity,
e.description as description,
head(collect(d.docID)) as document_id,
head(collect(d.chunkID)) as chunkID,
head(collect(d.full_text)) as document_text,
reduce(mDot = 0.0, i IN range(0, size($user_query_emb) - 1) | mDot + $user_query_emb[i] * e.embeddings[i]) /
(sqrt(reduce(mSq = 0.0, x IN $user_query_emb | mSq + x^2)) * sqrt(reduce(eSq = 0.0, y IN e.embeddings | eSq + y^2))) AS entity_similarity,
reduce(mDot = 0.0, i IN range(0, size($user_query_emb) - 1) | mDot + $user_query_emb[i] * d.embeddings[i]) /
(sqrt(reduce(mSq = 0.0, x IN $user_query_emb | mSq + x^2)) * sqrt(reduce(dSq = 0.0, y IN d.embeddings | dSq + y^2))) AS document_similarity
WITH id, title, description, document_id, document_text, entity_similarity, document_similarity, chunkID,
(entity_similarity + document_similarity) / 2 AS similarity, cosineSimilarity
WHERE similarity > 0.8
RETURN id, title, document_id, document_text, similarity, chunkID
ORDER BY cosineSimilarity DESC, similarity DESC
通过这个查询,我首先使用向量索引提取固定实体,然后识别最佳匹配的文档。接下来,我计算提取的实体与用户查询之间的点积,以及找到的文档与用户查询之间的点积。然后,我将这些结果结合起来,并根据0.8的阈值进行过滤。结合重新排序,这种方法产生了以下结果(表8):
表8 使用查询4包括重新排序的检索信息
通过这个实验,我旨在展示检索在图中的威力。 通过完全控制固定实体和添加文档的过程,并灵活构建几乎任何检索Cypher查询,其潜力是巨大的。 根据您的具体使用案例调整检索过程的自由几乎是无限的。 在这个实验中,我们使用了一个有限的固定实体架构,缺乏广泛的描述和元素之间的关系。 然而,通过结合更多的信息和连接,可以实现显著的结果。
本文探讨了使用图构建和查询知识库,重点介绍了固定实体架构及其在检索增强生成(RAG)系统中的应用。固定实体架构依赖于预定义的实体和关系来构建知识图谱,具有较低的复杂性、高精度和降低的计算成本等优点。然而,它在灵活性和可扩展性方面可能面临限制。
本文展示了如何使用“鱼骨图”本体构建知识图谱并将文档集成到图中。通过利用向量索引和Cypher查询,文档根据余弦相似度与实体连接。这种方法增强了检索能力,但可能需要优化以获得更好的结果。
进行了一系列查询以评估基于图的检索方法的有效性。初始查询使用向量索引和关键字搜索来查找匹配的实体和文档。尽管存在一些挑战,如重新排序结果不理想,本文展示了图在强大且灵活的检索中的潜力。最终的智能搜索查询结合向量相似度和点积计算,展示了该方法在优化搜索结果方面的有效性。
未来方向和创新
•改进机会 :增强基于LLM的提取方法和扩展预定义本体可以进一步优化知识图谱的能力。 •新兴趋势 :知识图谱开发中的新技术和进展可能会增强RAG系统,为复杂的检索任务提供更强大的解决方案。
总体而言,本文强调了图灵活的搜索能力的优势,以及优化实体连接和文档集成以实现高质量检索结果的重要性。提取技术的未来发展和新兴技术有望进一步推进知识图谱在RAG应用中的能力。
1.“From Local to Global: A Graph RAG Approach to Query-Focused Summarization”, Darren Edge 等人,2024年4月24日,计算机科学
引言 — Cypher手册 (neo4j.com)[1]
词嵌入 — 维基百科[2]
余弦相似度 — 维基百科[3]
什么是向量索引?向量索引入门 (datastax.com)[4]
阿尔伯特·爱因斯坦 — 维基百科[5]
相对论 — 维基百科[6]
理论物理学 — 维基百科[7]
天文学 — 维基百科[8]
声明
References
[1]
引言 — Cypher手册 (neo4j.com): https://neo4j.com/docs/cypher-manual/current/introduction/
[2]
词嵌入 — 维基百科: https://zh.wikipedia.org/wiki/%E8%AF%8D%E5%B9%BC%E8%BF%9E
[3]
余弦相似度 — 维基百科: https://zh.wikipedia.org/wiki/%E4%BD%99%E5%BC%A6%E7%9B%B8%E4%BC%BC%E5%BA%A6
[4]
什么是向量索引?向量索引入门 (datastax.com): https://www.datastax.com/guides/what-is-a-vector-index
[5]
阿尔伯特·爱因斯坦 — 维基百科: https://zh.wikipedia.org/wiki/%E9%98%BF%E5%B0%94%E4%BC%AF%E7%89%B9%C2%B7%E7%88%B1%E5%9B%A0%E6%96%AF%E5%BF%B5
[6]
相对论 — 维基百科: https://zh.wikipedia.org/wiki/%E7%9B%B8%E5%AF%B9%E8%AE%BA
[7]
理论物理学 — 维基百科: https://zh.wikipedia.org/wiki/%E7%90%86%E8%AB%96%E7%89%A9%E7%90%86%E5%AD%B8
[8]
天文学 — 维基百科: https://zh.wikipedia.org/wiki/%E5%A4%A9%E5%AD%A6