第一次完整的本地AI系统开发实战,包含数据库设计、向量检索、可编辑提示词和性能优化
📅 开发时间:2024年3月7日
👨💻 开发者:neuxiang
🎯 项目目标:
1.构建一个基于大模型的永久对话系统,所有数据本地存储,重启不丢失
2.用户自定义提示词控制
3.用户知识库管理
一、项目背景与技术选型
为什么要做这个项目?
在云端AI服务盛行的今天,数据隐私、离线可用、永久记忆成为许多开发者和企业的核心诉求。本项目旨在打造一个完全本地运行的智能对话系统,所有对话历史、知识库都存储在本地文件中,拷走即迁移,重启不丢失。
📌 技术栈
| 技术 | 版本 | 用途 |
|---|---|---|
| Spring Boot | 3.2.4 | 应用框架 |
| Java | 17 | 开发语言 |
| Spring AI | 1.0.0-M6 | AI应用框架(向量存储) |
| MyBatis-Plus | 3.5.8 | 持久层框架 |
| SQLite | 3.46.0 | 嵌入式数据库 |
| SimpleVectorStore | 1.0.0-M6 | 文件型向量库 |
| Ollama + Qwen3 | 4b | 本地大模型 |
| Lombok | - | 代码简化 |
| JUnit 5 | - | 单元测试 |
二、核心功能实现
2.1 数据库设计(5张表)
-- 会话表:管理所有对话窗口
CREATE TABLE sessions (id PRIMARY KEY, session_id, name, summary...);
-- 消息表:存储原始对话历史
CREATE TABLE messages (id, session_id, role, content, created_at...);
-- 摘要表:保存增量总结版本
CREATE TABLE summaries (id, session_id, summary, created_at...);
-- 知识库表:存储个人知识
CREATE TABLE knowledge (id, title, content, tags, vector_id...);
-- 向量元数据表:记录向量化状态
CREATE TABLE vector_meta (id, vector_id, entity_type, entity_id...);
2.2 可编辑提示词系统
实现了一个热加载的提示词管理系统,用户可以直接修改 .md 文件,无需重启应用:
// 文件结构
./prompts/
├── system.md # 系统角色设定
├── chat-template.md # 对话模板
├── summary-trigger.md # 总结时机判断
└── summary-content.md # 总结内容模板
2.3 向量知识库(RAG)
使用 Spring AI 的 SimpleVectorStore 实现文件型向量数据库:
// 添加知识时自动保存到向量库和JSON文件
public void addKnowledge(String title, String content) {
// 1. 保存到SQLite
KnowledgeEntity entity = new KnowledgeEntity();
entity.setContent(content);
knowledgeMapper.insert(entity);
// 2. 保存到向量库
Document doc = new Document(content);
vectorStore.add(List.of(doc));
// 3. 自动持久化到JSON文件
((SimpleVectorStore) vectorStore).save(new File("./data/vector-store.json"));
}
2.4 本地大模型集成
选用 Ollama + Qwen3:4b 作为推理引擎,实测性能:
指标 数据 生成速度 36 tokens/秒 首字响应 1.7秒(首次加载) 内存占用 ~3GB 硬件 Apple M4 24GB
三、性能优化挑战
3.1 遇到的挑战
初期通过 Spring AI 官方 Starter 调用时,响应时间长达 10-20秒,用户体验极差。
3.2 排查过程
通过对比测试定位问题:
# 测试Spring API
time curl -X POST http://localhost:8080/api/chat -d '{"message":"Hello"}'
# 耗时: 10-20秒
# 直接测试Ollama API
time curl -X POST http://localhost:11434/api/generate -d '{"model":"qwen3:4b","prompt":"Hello"}'
# 耗时: 8-11秒 ✅ 同样慢!
关键发现:问题不在Spring集成层,而在Ollama本身
四、测试与质量保障
4.1 单元测试覆盖
测试类 测试方法 场景 KnowledgeServiceTest testAddKnowledge 添加知识 testSaveToFile 手动保存 testSearchSimilar 向量搜索 testOnShutdown 关闭自动保存 ChatServiceTest testSendMessage 发送消息 testCreateSession 创建会话 testGetHistory 获取历史
最终成果:37个测试用例全部通过,核心功能稳定可靠。
4.2 构建验证
mvn clean install # ✅ BUILD SUCCESS
五、项目亮点总结
✅ 完全本地化(有性能问题,待定)
· 不依赖任何云端服务 · 所有数据存在 ./data/ 目录 · 拷走即迁移,重启不丢失
✅ 永久记忆
· SQLite 存储完整对话历史 · VectorStore 存储向量化知识 · 会话摘要自动压缩长对话
✅ 可扩展提示词
· 用户可编辑 .md 文件 · 热加载,修改即时生效 · REST API 支持动态更新
✅ 高性能设计
· 连接池优化 · 流式响应 · 量化模型加速
六、项目结构
persist_chat/
├── src/main/java/com/neuxiang/persistchat/
│ ├── config/ # AIConfig, VectorStoreConfig, HttpClientConfig
│ ├── controller/ # ChatController, KnowledgeController, PromptController
│ ├── service/ # ChatService, KnowledgeService, PromptService, OllamaService
│ ├── mapper/ # 5个MyBatis-Plus Mapper接口
│ └── entity/ # 5个实体类
├── data/ # SQLite数据库 + JSON向量库
├── prompts/ # 可编辑提示词文件
└── pom.xml # 依赖管理
七、下一步计划
功能 优先级 说明 流式前端 🔥 高 实现文字逐字显示效果 对话总结 ⏸️ 中 自动生成摘要存入向量库 个人知识库⏸️ 中 个人总结数据存入向量库
🎯 最终成果
一个功能完整、性能稳定、完全本地化的永久对话系统,包含:
✅ 多会话对话管理
✅ 永久历史存储
✅ 可编辑提示词
✅ 向量知识库RAG
✅ 本地大模型推理
✅ 完整的单元测试
所有代码已通过测试,可随时部署使用!
📝 技术总结
- Spring Boot + MyBatis-Plus 是快速构建持久层的黄金组合
- SimpleVectorStore 足够满足中小规模RAG需求
- Ollama + Qwen3 在Apple M4上表现一般(36 tokens/秒)
- 流式响应 是提升AI对话体验的关键
- 可编辑提示词 让非技术人员也能优化AI行为
项目状态: 基础架构完成 | 流式优化中 | 持续迭代