Spring AI 教程

Neo4j 数据库(Neo4jChatMemoryRepository)

提示:如果不能访问 OpenAI,请点击 AiCode API 注册账号,通过代理访问。  

在 Spring AI 1.0.0 中,Neo4jChatMemoryRepository 是用于将聊天记忆(对话历史)持久化到 Neo4j 图数据库的存储实现,它实现了 ChatMemoryRepository 接口,属于 Spring AI 聊天记忆模块的一部分。

Neo4jChatMemoryRepository 基于图数据库的特性,适合存储具有复杂关联关系的对话数据,尤其在需要对对话上下文进行多维度查询、分析或关联扩展时表现出色。

Neo4j 数据库

Neo4j 是一款开源的原生图数据库(Native Graph Database),专为存储、查询和处理具有复杂关联关系的数据而设计。它以 “图” 作为数据模型的核心,通过节点(Node)、关系(Relationship)和属性(Property)来表达数据及其之间的关联,相比传统的关系型数据库(如 MySQL)或文档数据库(如 MongoDB),在处理多对多关系、路径分析、关联挖掘等场景中具有显著优势。

Neo4j 数据库主要特性如下:

(1) 原生图存储数据从底层设计就以图结构存储,而非通过关系表或文档间接模拟图关系,因此对关联数据的读写性能远超其他类型数据库。

(2)高效的图查询语言Cypher提供声明式查询语言 Cypher,语法简洁直观,专为图操作设计,支持节点匹配、关系遍历、路径查找(如最短路径)、聚合分析等复杂操作。

(3)ACID 事务支持:完全支持事务的原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability),确保数据操作的可靠性。

(4)高可用性与扩展性:支持集群部署(主从复制、因果集群),提供自动故障转移和读写分离,可通过水平扩展应对大规模数据和高并发场景。

(5)丰富的生态与集成:提供多种编程语言驱动(Java、Python、JavaScript 等)、REST API、与大数据工具(Spark、Flink)和 AI 框架(如 Spring AI)的集成能力。

Neo4j 数据库的数据模型核心由三部分组成:

(1) 节点(Node):表示实体(如“用户”、“商品”、“订单”),可被打上一个或多个标签(Label,类似关系型数据库的“表”),用于分类节点(如 :User :Product)。

(2)关系(Relationship):连接两个节点,具有方向和类型(如 :FOLLOWS :PURCHASED),表示实体间的关联(如“用户 A 购买了商品 B”)。关系必须有且仅有一个类型,且不可独立存在(必连接两个节点)。

(3)属性(Property):键值对(Key-Value),可附加在节点或关系上,存储具体数据(如节点 :User 可有 name: "Alice" age: 30,关系 :PURCHASED 可有 amount: 99.9 time: "2023-10-01")。

注意,Neo4j 是图数据库领域的标杆产品,其核心价值在于高效处理“关系密集型”数据。当业务场景中数据间的关联是核心(如社交、知识图谱、推荐),Neo4j 相比传统数据库能显著提升开发效率和查询性能。

简单示例

安装 Neo4j

下面将演示在 Windows11 下面通过 WSL2 安装的 Ubuntu 22.04.5 LTS (GNU/Linux 6.6.87.2-microsoft-standard-WSL2 x86_64) 系统中,通过 Docker 安装 Apache Cassandra 数据库,详细步骤如下:

(1)查看 Docker 版本信息,如果没有 Docker 请先安装 Docker。如下:

hxstrive@localhost:~$ sudo docker --version
Docker version 28.3.2, build 578ccf6

安装 Docker 请参考 Docker 教程。

(2) 从 Docker Hub 拉取官方的 neo4j 镜像(默认会拉取最新稳定版),如下:

hxstrive@localhost:~$ sudo docker pull neo4j
[sudo] password for hx:
Using default tag: latest
latest: Pulling from library/neo4j
4eb1dd59a738: Pull complete
af4d3ed4f508: Pull complete
aa20373901d9: Pull complete
e259da529216: Pull complete
2aa9c2c55d90: Pull complete
4f4fb700ef54: Pull complete
Digest: sha256:0c83938a8d825ade6e42ab81c4ab9a99a7e7ff05fb2fd248fd0636bbc6aa9aab
Status: Downloaded newer image for neo4j:latest
docker.io/library/neo4j:latest

(3)使用 docker run 命令启动 Neo4j 容器,需配置必要的端口映射、数据持久化和环境变量。如果仅用于临时测试,无需持久化数据,可直接运行:

docker run \
  --name neo4j-test \
  -d \
  -p 7474:7474 \  # Web 管理界面端口
  -p 7687:7687 \  # Bolt 协议端口(客户端连接用)
  -e NEO4J_AUTH=neo4j/password \  # 用户名/密码(默认用户为 neo4j)
  neo4j

参数说明:

  • --name neo4j-test:给容器命名(方便后续操作)。

  • -d:后台运行容器。

  • -p 7474:7474:将容器内的 7474 端口映射到主机的 7474 端口(Web 界面访问)。

  • -p 7687:7687:Bolt 协议端口,用于客户端(如 Java/Python 驱动)连接。

  • -e NEO4J_AUTH=neo4j/password:设置初始密码(首次登录需使用此密码,建议修改为复杂密码)。

hxstrive@localhost:~$ sudo docker run --name neo4j-test -d -p 7474:7474 -p 7687:7687 -e NEO4J_AUTH=neo4j/1234abcd neo4j
85f7a8d856029e726c27d6a44511fbbabfbddcdf4c22c2996e641e5c8b543471

(4)验证 Neo4j 运行状态,使用 docker ps | grep neo4j 查看容器是否启动成功。如果输出包含 neo4j 容器信息,说明启动成功,如下:

hxstrive@localhost:~$ sudo docker ps | grep neo4j
85f7a8d85602   neo4j       "tini -g -- /startup…"   9 seconds ago   Up 9 seconds   0.0.0.0:7474->7474/tcp, [::]:7474->7474/tcp, 7473/tcp, 0.0.0.0:7687->7687/tcp, [::]:7687->7687/tcp   neo4j-test

还可以继续使用 docker logs 命令查看启动日志:

hxstrive@localhost:~$ sudo docker logs neo4j-test
Changed password for user 'neo4j'. IMPORTANT: this change will only take effect if performed before the database is started for the first time.
2025-10-17 07:02:24.589+0000 INFO  Logging config in use: File '/var/lib/neo4j/conf/user-logs.xml'
2025-10-17 07:02:24.622+0000 INFO  Starting...
2025-10-17 07:02:26.206+0000 INFO  This instance is ServerId{36c81561} (36c81561-eaeb-498c-b567-b503262ab95a)
2025-10-17 07:02:29.192+0000 INFO  ======== Neo4j 2025.09.0 ========
2025-10-17 07:02:32.296+0000 INFO  Anonymous Usage Data is being sent to Neo4j, see https://neo4j.com/docs/usage-data/
2025-10-17 07:02:34.144+0000 INFO  Bolt enabled on 0.0.0.0:7687.
2025-10-17 07:02:36.052+0000 INFO  HTTP enabled on 0.0.0.0:7474.
2025-10-17 07:02:36.053+0000 INFO  Remote interface available at http://localhost:7474/
2025-10-17 07:02:36.057+0000 INFO  id: 9C1D6E955A82DA9A7218883E76600EA437B37510F82451FB9DF7F04A30D9CE27
2025-10-17 07:02:36.058+0000 INFO  name: system
2025-10-17 07:02:36.058+0000 INFO  creationDate: 2025-10-17T07:02:31.142Z
2025-10-17 07:02:36.059+0000 INFO  Started.

日志末尾出现了 Started. 表示服务已就绪。

(5)访问 Neo4j 管理界面

打开浏览器,访问 http://localhost:7474(如果是远程服务器,替换为服务器 IP)。首次登录时,输入用户名 neo4j 和设置的密码(如 1234abcd)。

注意,登录后会提示修改初始密码,建议设置一个新密码(后续客户端连接需使用新密码)。

Neo4j 数据库(Neo4jChatMemoryRepository)

Neo4j 数据库(Neo4jChatMemoryRepository)

添加依赖

首先,在项目中添加以下依赖:

<dependency>
  <groupId>org.springframework.ai</groupId>
  <artifactId>spring-ai-model-chat-memory-repository-neo4j</artifactId>
</dependency>

注意:spring-ai-model-chat-memory-repository-neo4j 是专门用于将 聊天记忆(对话历史)持久化到 Neo4j 图数据库 的模块,提供了基于图结构的对话记忆管理能力。

编写代码

到这里,准备工作就做完了,下面开始编写代码。

首先,创建一个名为 AiConfig.java 的配置类,用来配置 ChatMemory 和 Neo4jChatMemoryRepository,代码如下:

package com.hxstrive.springai.springai_openai.chatMemoryRepository.chatMemoryRepository4;

import org.neo4j.driver.Driver;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.chat.memory.repository.neo4j.Neo4jChatMemoryRepository;
import org.springframework.ai.chat.memory.repository.neo4j.Neo4jChatMemoryRepositoryConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AiConfig {

    /**
     * 定义聊天记忆(ChatMemory)Bean
     * 采用窗口模式(MessageWindowChatMemory),限制最多保存的消息数量
     *
     * @param chatMemoryRepository 聊天记忆存储仓库(Neo4j实现)
     * @return 配置好的聊天记忆对象
     */
    @Bean
    public ChatMemory chatMemory(Neo4jChatMemoryRepository chatMemoryRepository) {
        return MessageWindowChatMemory.builder()
        .chatMemoryRepository(chatMemoryRepository) // 注入Neo4j存储仓库,指定消息持久化方式
        .maxMessages(20) // 设置窗口大小,最多保存20条消息(超过则自动丢弃最早的消息)
        .build();
    }

    @Bean
    public Neo4jChatMemoryRepository cassandraChatMemoryRepository(Driver driver) {
        Neo4jChatMemoryRepositoryConfig config = Neo4jChatMemoryRepositoryConfig.builder()
        .withDriver(driver)
        .build();
        return new Neo4jChatMemoryRepository(config);
    }

}

然后,将 ChatMemory 注入到客户端代码中,如下:

package com.hxstrive.springai.springai_openai.chatMemoryRepository.chatMemoryRepository4;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RestController;

@RestController
@SpringBootApplication
public class SpringAiDemoApplication implements CommandLineRunner {

	@Autowired
	private ChatModel chatModel;

	@Autowired
	private ChatMemory chatMemory;

	public static void main(String[] args) {
		SpringApplication.run(SpringAiDemoApplication.class, args);
	}

	@Override
	public void run(String... args) throws Exception {
		StringBuilder builder = new StringBuilder();

		// 唯一会话ID,同一个会话上下文中保持一致
		String sessionId = "USER-251017100313";

		String question = "四川大学是985吗?";
		String ai = chat(sessionId, question);
		builder.append(String.format("用户问题:%s\n", question));
		builder.append(String.format("机器回复:%s\n", ai));

		question = "是211吗?";
		ai = chat(sessionId, question);
		builder.append(String.format("用户问题:%s\n", question));
		builder.append(String.format("机器回复:%s\n", ai));

		System.out.println(builder.toString());
	}

	private String chat(String sessionId, String question) {
		ChatClient chatClient = ChatClient.builder(chatModel)
				.defaultSystem("你是AI助手小粒,所有回复均使用中文。")
				.defaultAdvisors(
						new SimpleLoggerAdvisor() // 输出聊天日志
				).build();

		// 1. 将用户输入添加到记忆
		UserMessage userMessage = new UserMessage(question);
		chatMemory.add(sessionId, userMessage);

		// 2. 获取记忆中的所有消息(上下文),传递给 AI 模型
		ChatClient.CallResponseSpec responseSpec = chatClient.prompt().messages(chatMemory.get(sessionId)).call();

		// 3. 将 AI 回复添加到记忆,更新上下文
		AssistantMessage assistantMessage = responseSpec.chatResponse().getResult().getOutput();
		chatMemory.add(sessionId, assistantMessage);

		// 4. 返回 AI 回复内容
		return assistantMessage.getText();
	}

}

运行代码,输出如下:

Neo4j 数据库(Neo4jChatMemoryRepository)

执行成功后,登录到 Neo4j 的 Web 页面,查看刚刚存入的数据。如下图:

Neo4j 数据库(Neo4jChatMemoryRepository)

Neo4j 数据库(Neo4jChatMemoryRepository)

配置属性

下面是 Spring AI 中,关于 neo4j 的配置项:

属性

说明

默认值

spring.ai.chat.memory.repository.neo4j.sessionLabel

存储对话会话的节点的标签

Session

spring.ai.chat.memory.repository.neo4j.messageLabel

存储信息的节点的标签

Message

spring.ai.chat.memory.repository.neo4j.toolCallLabel

存储工具调用的节点(如 Assistant 信息中)的标签

ToolCall

spring.ai.chat.memory.repository.neo4j.metadataLabel

存储消息元数据的节点的标签

Metadata

spring.ai.chat.memory.repository.neo4j.toolResponseLabel

存储工具响应的节点的标签

ToolResponse

spring.ai.chat.memory.repository.neo4j.mediaLabel

存储消息相关的媒体的节点标签

Media

注意:Neo4j 存储库将自动创建会话 ID 和消息索引的优化索引。若使用自定义标签,系统同样会为这些标签建立索引。虽无需初始化 Schema,但需确保应用可访问 Neo4j 实例。

更多信息请访问官方文档 https://docs.spring.io/spring-ai/reference/api/vectordbs/neo4j.html

  

提示:如果不能访问 OpenAI,请点击 AiCode API 注册账号,通过代理访问。  

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
其他应用
公众号