使用云 AI 提供商创建嵌入

Cypher® 函数 genai.vector.encode 和过程 genai.vector.encodeBatch 允许您通过外部 AI 提供商为一个或多个文本片段生成嵌入。您需要一个受支持提供商(OpenAI、Vertex AI、Azure OpenAI、Amazon Bedrock)的 API 令牌。

此页面假设您已 导入推荐数据集设置您的环境,并展示如何基于电影标题和剧情为 Movie 节点生成和存储嵌入。

嵌入始终在 Neo4j 外部 生成,但在 Neo4j 数据库中存储

设置环境

编码函数是 Neo4j GenAI 插件的一部分。

  • 在 Aura 实例上,插件默认启用,因此如果您在 Aura 上使用 Neo4j,则无需执行任何其他操作。

  • 对于自管理实例,需要安装插件。您可以通过将 neo4j-genai.jar 文件从 Neo4j 主目录中的 /products 移动到 /plugins,或通过使用额外参数 --env NEO4J_PLUGINS='["genai"]' 启动 Docker 容器来执行此操作。
    有关更多信息,请参阅 配置→插件

为电影创建嵌入

以下示例从数据库中获取所有 Movie 节点,生成电影标题和剧情连接的嵌入,并将其作为额外 embedding 属性添加到每个节点。

import neo4j


URI = '<URI for Neo4j database>'
AUTH = ('<Username>', '<Password>')
DB_NAME = '<Database name>'  # examples: 'recommendations-50', 'neo4j'

openAI_token = '<OpenAI API token>'


def main():
    driver = neo4j.GraphDatabase.driver(URI, auth=AUTH)  (1)
    driver.verify_connectivity()

    batch_size = 100
    batch_n = 1
    movies_batch = []
    with driver.session(database=DB_NAME) as session:
        # Fetch `Movie` nodes
        result = session.run('MATCH (m:Movie) RETURN m.plot AS plot, m.title AS title')
        for record in result:
            title = record.get('title')
            plot = record.get('plot')

            if title is not None and plot is not None:
                movies_batch.append({
                    'title': title,
                    'plot': plot,
                    'to_encode': f'Title: {title}\nPlot: {plot}'  (2)
                })

            # Import a batch; flush buffer
            if len(movies_batch) == batch_size:  (3)
                import_batch(driver, movies_batch, batch_n)
                movies_batch = []
                batch_n += 1

    # Import complete, show counters
    records, _, _ = driver.execute_query('''
    MATCH (m:Movie WHERE m.embedding IS NOT NULL)
    RETURN count(*) AS countMoviesWithEmbeddings, size(m.embedding) AS embeddingSize
    ''', database_=DB_NAME)
    print(f"""
Embeddings generated and attached to nodes.
Movie nodes with embeddings: {records[0].get('countMoviesWithEmbeddings')}.
Embedding size: {records[0].get('embeddingSize')}.
    """)


def import_batch(driver, nodes, batch_n):
    # Generate and store embeddings for Movie nodes
    driver.execute_query('''
    CALL genai.vector.encodeBatch($to_encode_list, 'OpenAI', { token: $token }) YIELD index, vector  (4)
    MATCH (m:Movie {title: $movies[index].title, plot: $movies[index].plot})  (5)
    CALL db.create.setNodeVectorProperty(m, 'embedding', vector)  (6)
    ''', movies=nodes, to_encode_list=[movie['to_encode'] for movie in nodes], token=openAI_token,
    database_=DB_NAME)
    print(f'Processed batch {batch_n}')


if __name__ == '__main__':
    main()

'''
Movie nodes with embeddings: 9083.
Embedding size: 1536.
'''
1 driver 对象是与 Neo4j 实例交互的接口。有关更多信息,请参阅 使用 Neo4j 和 Python 构建应用程序
2 OpenAI 应将其编码为嵌入的字符串。
3 在将整个批次提交到数据库之前,会收集一定数量的嵌入。这避免了将整个数据集保留在内存中以及潜在的超时(对于较大的数据集尤其重要)。
4 过程 genai.vector.encodeBatch() 将批次提交给 OpenAI 进行编码。OpenAI 的默认模型为 text-embedding-ada-002,它将文本嵌入到大小为 1536 的向量中(即 1536 个数字的列表)。请参阅 GenAI 提供商,了解受支持的提供商和选项列表。
5 genai.vector.encodeBatch 返回的 index 允许将嵌入与电影关联起来,以便可以检索每个电影节点并将其嵌入附加到该节点。
6 过程 db.create.setNodeVectorProperty 将嵌入 vector 存储在每个电影节点 m 的名为 embedding 的属性中。使用过程添加嵌入比使用 SET Cypher 子句更有效。要设置关系上的向量属性,请使用 db.create.setRelationshipVectorProperty

将嵌入放入数据库后,您可以使用它们来 比较一部电影与另一部电影的相似程度