feat: 添加 RAG 文档问答功能
- 新增 DocumentController 提供文档导入 API - 新增 DocumentService 实现文档读取、分割、向量化存储 - 新增 RagConfig 配置 TokenTextSplitter - 添加 doris_intro.md 作为示例 RAG 文档 - 启用 milvus-sdk-java 依赖 - 配置 SiliconFlow Embedding 服务 (BAAI/bge-large-zh-v1.5) - 配置 Milvus 向量数据库连接
This commit is contained in:
parent
3208efe280
commit
43891f876e
157
README.md
157
README.md
@ -1,6 +1,6 @@
|
|||||||
# Spring AI Demo
|
# Spring AI Demo
|
||||||
|
|
||||||
> 🤖 一个简洁优雅的 Spring AI 对话演示项目,基于 Spring Boot 3.2.0 与 Spring AI 1.0.0-M3 构建,支持流式响应与 Markdown 渲染。
|
> 🤖 一个简洁优雅的 Spring AI 对话演示项目,基于 Spring Boot 3.2.0 与 Spring AI 1.0.0-M3 构建,支持流式响应、Markdown 渲染与 RAG 文档问答。
|
||||||
|
|
||||||
[](https://spring.io/projects/spring-boot)
|
[](https://spring.io/projects/spring-boot)
|
||||||
[](https://spring.io/projects/spring-ai)
|
[](https://spring.io/projects/spring-ai)
|
||||||
@ -13,7 +13,9 @@
|
|||||||
- 📡 **流式响应** - 实时逐字输出,体验流畅
|
- 📡 **流式响应** - 实时逐字输出,体验流畅
|
||||||
- 📝 **Markdown 支持** - 完整渲染代码块、表格、列表等格式
|
- 📝 **Markdown 支持** - 完整渲染代码块、表格、列表等格式
|
||||||
- 👨💻 **代码高亮** - Highlight.js 自动语言检测与语法着色
|
- 👨💻 **代码高亮** - Highlight.js 自动语言检测与语法着色
|
||||||
- 🖼️ **向量数据库** - Milvus 集成(预留 RAG 扩展能力)
|
- 📚 **RAG 文档问答** - 文档向量化存储,智能语义检索
|
||||||
|
- 🗃️ **向量数据库** - Milvus 分布式向量数据库集成
|
||||||
|
- 🔍 **Embedding 服务** - SiliconFlow BAAI/bge-large-zh-v1.5
|
||||||
- 📔 **PDF 解析** - Apache PDFBox 文档处理支持
|
- 📔 **PDF 解析** - Apache PDFBox 文档处理支持
|
||||||
- 🎨 **精美界面** - 深色主题响应式设计
|
- 🎨 **精美界面** - 深色主题响应式设计
|
||||||
|
|
||||||
@ -24,6 +26,7 @@
|
|||||||
- JDK 17+
|
- JDK 17+
|
||||||
- Maven 3.8+
|
- Maven 3.8+
|
||||||
- [Ollama](https://ollama.ai/) 本地服务
|
- [Ollama](https://ollama.ai/) 本地服务
|
||||||
|
- Milvus 向量数据库(可选,用于 RAG)
|
||||||
|
|
||||||
### 1. 安装 Ollama
|
### 1. 安装 Ollama
|
||||||
|
|
||||||
@ -58,8 +61,9 @@ mvn spring-boot:run
|
|||||||
| 基础框架 | Spring Boot | 3.2.0 |
|
| 基础框架 | Spring Boot | 3.2.0 |
|
||||||
| AI 框架 | Spring AI | 1.0.0-M3 |
|
| AI 框架 | Spring AI | 1.0.0-M3 |
|
||||||
| AI 模型 | OpenAI/Ollama | - |
|
| AI 模型 | OpenAI/Ollama | - |
|
||||||
|
| Embedding | SiliconFlow BAAI/bge-large-zh-v1.5 | - |
|
||||||
|
| 向量数据库 | Milvus | 2.3.4 |
|
||||||
| 响应式编程 | Spring WebFlux | 3.2.0 |
|
| 响应式编程 | Spring WebFlux | 3.2.0 |
|
||||||
| 向量数据库 | Milvus Store | 1.0.0-M3 |
|
|
||||||
| 文档处理 | Apache PDFBox | 2.0.29 |
|
| 文档处理 | Apache PDFBox | 2.0.29 |
|
||||||
|
|
||||||
### 前端
|
### 前端
|
||||||
@ -77,22 +81,29 @@ springAiDemo/
|
|||||||
├── src/
|
├── src/
|
||||||
│ └── main/
|
│ └── main/
|
||||||
│ ├── java/com/demo/
|
│ ├── java/com/demo/
|
||||||
│ │ ├── MyApplication.java # Spring Boot 启动入口
|
│ │ ├── MyApplication.java # Spring Boot 启动入口
|
||||||
│ │ └── controller/
|
│ │ ├── config/
|
||||||
│ │ └── ChatController.java # AI 聊天 REST API
|
│ │ │ └── RagConfig.java # RAG 文本分割配置
|
||||||
|
│ │ ├── controller/
|
||||||
|
│ │ │ ├── ChatController.java # AI 聊天 REST API
|
||||||
|
│ │ │ └── DocumentController.java # 文档导入 REST API
|
||||||
|
│ │ └── service/
|
||||||
|
│ │ └── DocumentService.java # 文档处理服务
|
||||||
│ └── resources/
|
│ └── resources/
|
||||||
│ ├── application.yaml # 应用配置
|
│ ├── application.yaml # 应用配置
|
||||||
│ └── static/ # 前端静态资源
|
│ └── static/ # 前端静态资源
|
||||||
│ ├── index.html # 主页面
|
│ ├── index.html # 主页面
|
||||||
│ ├── css/style.css # 深色主题样式
|
│ ├── css/style.css # 深色主题样式
|
||||||
│ └── js/app.js # 流式响应逻辑
|
│ └── js/app.js # 流式响应逻辑
|
||||||
|
├── data/
|
||||||
|
│ └── doris_intro.md # RAG 示例文档
|
||||||
├── pom.xml
|
├── pom.xml
|
||||||
└── README.md
|
└── README.md
|
||||||
```
|
```
|
||||||
|
|
||||||
## 💬 API 文档
|
## 💬 API 文档
|
||||||
|
|
||||||
### 端点列表
|
### 聊天接口
|
||||||
|
|
||||||
| 方法 | 端点 | 描述 | 参数 |
|
| 方法 | 端点 | 描述 | 参数 |
|
||||||
|:---|:---|:---|:---|
|
|:---|:---|:---|:---|
|
||||||
@ -100,6 +111,12 @@ springAiDemo/
|
|||||||
| GET | `/api/chat/ai` | 同步 AI 对话 | `msg` |
|
| GET | `/api/chat/ai` | 同步 AI 对话 | `msg` |
|
||||||
| GET | `/api/chat/ai/stream` | 流式 AI 对话 | `msg` |
|
| GET | `/api/chat/ai/stream` | 流式 AI 对话 | `msg` |
|
||||||
|
|
||||||
|
### 文档接口
|
||||||
|
|
||||||
|
| 方法 | 端点 | 描述 | 参数 |
|
||||||
|
|:---|:---|:---|:---|
|
||||||
|
| GET | `/api/documents/import` | 导入文档到向量库 | - |
|
||||||
|
|
||||||
### 请求示例
|
### 请求示例
|
||||||
|
|
||||||
**同步对话:**
|
**同步对话:**
|
||||||
@ -112,10 +129,36 @@ curl "http://localhost:8080/api/chat/ai?msg=什么是Spring AI"
|
|||||||
curl "http://localhost:8080/api/chat/ai/stream?msg=讲一个故事"
|
curl "http://localhost:8080/api/chat/ai/stream?msg=讲一个故事"
|
||||||
```
|
```
|
||||||
|
|
||||||
### 响应格式
|
**导入 RAG 文档:**
|
||||||
|
```bash
|
||||||
|
curl http://localhost:8080/api/documents/import
|
||||||
|
```
|
||||||
|
|
||||||
- **同步**: `text/plain` - 完整回复文本
|
## 📚 RAG 文档问答
|
||||||
- **流式**: `text/html;charset=UTF-8` - Server-Sent Events 分块传输
|
|
||||||
|
### 功能说明
|
||||||
|
|
||||||
|
将本地文档导入 Milvus 向量数据库,实现基于语义理解的智能问答。
|
||||||
|
|
||||||
|
### 使用步骤
|
||||||
|
|
||||||
|
1. 将 `.md` 或 `.txt` 文档放入 `data/` 目录
|
||||||
|
2. 启动应用
|
||||||
|
3. 调用导入接口:
|
||||||
|
```bash
|
||||||
|
curl http://localhost:8080/api/documents/import
|
||||||
|
```
|
||||||
|
4. 通过聊天界面提问相关问题
|
||||||
|
|
||||||
|
### 文档处理配置
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
document:
|
||||||
|
data-path: data # 文档目录
|
||||||
|
chunk-size: 400 # 分割块大小 (tokens)
|
||||||
|
min-chunk-size: 200 # 最小块大小
|
||||||
|
max-num-chunk: 10000 # 最大块数量
|
||||||
|
```
|
||||||
|
|
||||||
## 🎨 界面预览
|
## 🎨 界面预览
|
||||||
|
|
||||||
@ -133,7 +176,7 @@ curl "http://localhost:8080/api/chat/ai/stream?msg=讲一个故事"
|
|||||||
|
|
||||||
## 🛠️ 配置说明
|
## 🛠️ 配置说明
|
||||||
|
|
||||||
### 模型配置 (`application.yaml`)
|
### AI 对话配置
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
spring:
|
spring:
|
||||||
@ -142,61 +185,87 @@ spring:
|
|||||||
base-url: http://localhost:11434 # Ollama 服务地址
|
base-url: http://localhost:11434 # Ollama 服务地址
|
||||||
chat:
|
chat:
|
||||||
options:
|
options:
|
||||||
model: gpt-oss:120b-cloud # 当前模型
|
model: gpt-oss:120b-cloud # 对话模型
|
||||||
temperature: 0.7 # 生成温度
|
temperature: 0.7
|
||||||
```
|
```
|
||||||
|
|
||||||
**支持模型**(需在 Ollama 中预先拉取):
|
### Embedding 配置
|
||||||
- `gpt-oss:120b-cloud` - 默认模型
|
|
||||||
- `kimi-k2.5:cloud` - Kimi 模型
|
```yaml
|
||||||
- `gemma4:e2b` - Google Gemma 模型
|
spring:
|
||||||
|
ai:
|
||||||
|
openai:
|
||||||
|
embedding:
|
||||||
|
api-key: your-siliconflow-api-key
|
||||||
|
base-url: https://api.siliconflow.cn
|
||||||
|
model: BAAI/bge-large-zh-v1.5
|
||||||
|
dimensions: 1024
|
||||||
|
enabled: true
|
||||||
|
```
|
||||||
|
|
||||||
|
### 向量数据库配置
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
spring:
|
||||||
|
ai:
|
||||||
|
vectorstore:
|
||||||
|
milvus:
|
||||||
|
host: 192.168.50.103
|
||||||
|
port: 19530
|
||||||
|
database-name: doris_docs
|
||||||
|
collection-name: vector_store
|
||||||
|
embedding-dimension: 1024
|
||||||
|
index-type: IVF_FLAT
|
||||||
|
metric-type: COSINE
|
||||||
|
```
|
||||||
|
|
||||||
## 🎬 架构图
|
## 🎬 架构图
|
||||||
|
|
||||||
```
|
```
|
||||||
┌─────────────┐ ┌──────────────────┐ ┌─────────────────┐
|
┌─────────────┐ ┌──────────────────┐ ┌─────────────────┐
|
||||||
│ Client │────▶│ ChatController │────▶│ ChatClient │
|
│ Client │────▶│ ChatController │────▶│ ChatClient │
|
||||||
│ (HTTP) │ │ (Spring MVC) │ │ (Spring AI) │
|
│ (HTTP) │ │ (Spring MVC) │ │ (Spring AI) │
|
||||||
└─────────────┘ └──────────────────┘ └────────┬────────┘
|
└─────────────┘ └──────────────────┘ └────────┬────────┘
|
||||||
│
|
│
|
||||||
▼
|
┌──────────────────┐ │
|
||||||
┌─────────────────┐
|
│ DocumentService │ │
|
||||||
│ Ollama/OpenAI │
|
│ (文档处理) │ ▼
|
||||||
│ (LLM Provider) │
|
└────────┬─────────┘ ┌─────────────────┐
|
||||||
└─────────────────┘
|
│ │ Ollama/OpenAI │
|
||||||
|
▼ │ (LLM Provider) │
|
||||||
|
┌──────────────────┐ └─────────────────┘
|
||||||
|
│ Milvus Store │
|
||||||
|
│ (向量存储) │
|
||||||
|
└──────────────────┘
|
||||||
```
|
```
|
||||||
|
|
||||||
## 📄 预留功能
|
## 📄 预留功能
|
||||||
|
|
||||||
以下依赖已集成,可按需启用:
|
以下依赖已集成,可按需启用:
|
||||||
|
|
||||||
- 🔍 **Milvus 向量数据库** - RAG 语义搜索
|
- 📔 **PDF 文档解析** - Apache PDFBox 文档处理
|
||||||
- 📔 **PDF 文档解析** - 文档上传与处理
|
|
||||||
- 🗨️ **Embedding 服务** - 文本向量化
|
|
||||||
|
|
||||||
## 👷 已知限制
|
## 👷 已知限制
|
||||||
|
|
||||||
1. 暂无对话历史持久化
|
1. 暂无对话历史持久化
|
||||||
2. 暂未实现请求频率限制
|
2. 暂未实现请求频率限制
|
||||||
3. JUnit 版本较旧(3.8.1),建议升级至 JUnit 5
|
3. Milvus 连接信息硬编码在配置中
|
||||||
|
|
||||||
## 📖 待办事项
|
## 📖 更新日志
|
||||||
|
|
||||||
- [ ] 添加全局异常处理
|
### v1.0.0 (2026-04-19)
|
||||||
- [ ] 实现 RAG 文档问答
|
|
||||||
- [ ] 对话历史存储
|
|
||||||
- [ ] 动态模型切换 API
|
|
||||||
- [ ] Docker 部署支持
|
|
||||||
- [ ] 单元测试完善
|
|
||||||
|
|
||||||
## 📤 更新日志
|
|
||||||
|
|
||||||
### v1.0.0 (2026-04-17)
|
|
||||||
- 🎉 初始版本发布
|
- 🎉 初始版本发布
|
||||||
- 支持流式 AI 对话
|
- 支持流式 AI 对话
|
||||||
- Markdown 渲染与代码高亮
|
- Markdown 渲染与代码高亮
|
||||||
- 深色主题 Web 界面
|
- 深色主题 Web 界面
|
||||||
|
|
||||||
|
### v1.1.0 (2026-04-19)
|
||||||
|
- ✨ 新增 RAG 文档问答功能
|
||||||
|
- ✨ 新增 DocumentController 文档导入 API
|
||||||
|
- ✨ 新增 DocumentService 文档处理服务
|
||||||
|
- ✨ 配置 SiliconFlow Embedding 服务
|
||||||
|
- ✨ 集成 Milvus 向量数据库
|
||||||
|
|
||||||
## 📗 License
|
## 📗 License
|
||||||
|
|
||||||
MIT © 2026 Spring AI Demo
|
MIT © 2026 Spring AI Demo
|
||||||
|
|||||||
98
data/doris_intro.md
Normal file
98
data/doris_intro.md
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
# Apache Doris 简介
|
||||||
|
|
||||||
|
Apache Doris 是一个基于 MPP 架构的高性能、实时的分析型数据库,以极速易用的特点被人们所熟知,仅需亚秒级响应时间即可返回海量数据下的查询结果,不仅可以支持高并发的点查询场景,也能支持高吞吐的复杂分析场景。
|
||||||
|
|
||||||
|
## 核心特性
|
||||||
|
|
||||||
|
### 1. 极速易用
|
||||||
|
|
||||||
|
Apache Doris 采用了列式存储引擎,通过向量化执行引擎和查询优化器,能够在海量数据下实现亚秒级的查询响应。同时,Doris 提供了标准 SQL 支持,用户无需学习新的查询语言,即可快速上手。
|
||||||
|
|
||||||
|
### 2. 高可用性
|
||||||
|
|
||||||
|
Doris 采用了多副本机制,数据自动备份,节点故障时可以自动切换,保证服务的高可用性。支持在线扩缩容,不影响业务运行。
|
||||||
|
|
||||||
|
### 3. 实时分析
|
||||||
|
|
||||||
|
Doris 支持实时数据导入和查询,数据导入后即可被查询,无需等待数据预处理。支持多种数据导入方式,包括 Stream Load、Broker Load、Routine Load 等。
|
||||||
|
|
||||||
|
### 4. 联邦查询
|
||||||
|
|
||||||
|
Doris 支持通过外部表的方式查询其他数据源,如 MySQL、Hive、Iceberg、Hudi 等,实现数据联邦查询,无需数据搬迁。
|
||||||
|
|
||||||
|
## 技术架构
|
||||||
|
|
||||||
|
Apache Doris 采用 MySQL 协议,高度兼容 MySQL 语法,支持标准 SQL。整体架构分为两层:
|
||||||
|
|
||||||
|
### Frontend (FE)
|
||||||
|
|
||||||
|
FE 主要负责:
|
||||||
|
- 接收和解析用户请求
|
||||||
|
- 查询规划和优化
|
||||||
|
- 元数据管理
|
||||||
|
- 集群管理
|
||||||
|
|
||||||
|
FE 节点分为 Follower 和 Observer 两种角色,Follower 参与选举和写入,Observer 只用于扩展查询能力。
|
||||||
|
|
||||||
|
### Backend (BE)
|
||||||
|
|
||||||
|
BE 主要负责:
|
||||||
|
- 数据存储
|
||||||
|
- 查询执行
|
||||||
|
- 数据导入
|
||||||
|
|
||||||
|
BE 节点负责数据的存储和计算,采用列式存储和向量化执行引擎,提供高性能的查询能力。
|
||||||
|
|
||||||
|
## 使用场景
|
||||||
|
|
||||||
|
### 1. 报表分析
|
||||||
|
|
||||||
|
适用于各类报表场景,支持复杂的多维分析,亚秒级响应,支持高并发查询。
|
||||||
|
|
||||||
|
### 2. 即席查询
|
||||||
|
|
||||||
|
支持灵活的即席查询,用户可以快速探索数据,发现业务洞察。
|
||||||
|
|
||||||
|
### 3. 实时数仓
|
||||||
|
|
||||||
|
构建实时数据仓库,支持实时数据导入和查询,满足实时分析需求。
|
||||||
|
|
||||||
|
### 4. 日志分析
|
||||||
|
|
||||||
|
适用于日志分析场景,支持海量日志数据的快速检索和分析。
|
||||||
|
|
||||||
|
## 数据导入
|
||||||
|
|
||||||
|
Apache Doris 支持多种数据导入方式:
|
||||||
|
|
||||||
|
### Stream Load
|
||||||
|
|
||||||
|
通过 HTTP 协议导入数据,适用于实时数据导入场景。支持 CSV、JSON 等格式。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl --location-trusted -u user:passwd \
|
||||||
|
-H "column_separator:," \
|
||||||
|
-T data.csv \
|
||||||
|
http://fe_host:http_port/api/database/table/_stream_load
|
||||||
|
```
|
||||||
|
|
||||||
|
### Broker Load
|
||||||
|
|
||||||
|
通过 Broker 进程访问外部存储系统(如 HDFS、S3)导入数据,适用于大批量数据导入。
|
||||||
|
|
||||||
|
### Routine Load
|
||||||
|
|
||||||
|
从 Kafka 等消息队列持续消费数据并导入,适用于实时数据流场景。
|
||||||
|
|
||||||
|
## 查询优化
|
||||||
|
|
||||||
|
Apache Doris 提供了多种查询优化手段:
|
||||||
|
|
||||||
|
1. **智能索引**:支持前缀索引、Bitmap 索引、Bloom Filter 索引等
|
||||||
|
2. **分区分桶**:通过合理的分区分桶策略,减少数据扫描量
|
||||||
|
3. **物化视图**:预计算常用查询结果,加速查询响应
|
||||||
|
4. **查询缓存**:缓存查询结果,避免重复计算
|
||||||
|
|
||||||
|
## 总结
|
||||||
|
|
||||||
|
Apache Doris 是一款高性能、易用的分析型数据库,适用于多种实时分析场景。通过 MPP 架构、列式存储、向量化执行等技术,提供亚秒级的查询响应能力。
|
||||||
12
pom.xml
12
pom.xml
@ -48,12 +48,12 @@
|
|||||||
<artifactId>spring-ai-milvus-store-spring-boot-starter</artifactId>
|
<artifactId>spring-ai-milvus-store-spring-boot-starter</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- <!– milvus客户端 –>-->
|
<!-- milvus客户端 -->
|
||||||
<!-- <dependency>-->
|
<dependency>
|
||||||
<!-- <groupId>io.milvus</groupId>-->
|
<groupId>io.milvus</groupId>
|
||||||
<!-- <artifactId>milvus-sdk-java</artifactId>-->
|
<artifactId>milvus-sdk-java</artifactId>
|
||||||
<!-- <version>2.3.4</version>-->
|
<version>2.3.4</version>
|
||||||
<!-- </dependency>-->
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
<!-- spring中用于校验的包 -->
|
<!-- spring中用于校验的包 -->
|
||||||
|
|||||||
27
src/main/java/com/demo/config/RagConfig.java
Normal file
27
src/main/java/com/demo/config/RagConfig.java
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package com.demo.config;
|
||||||
|
|
||||||
|
import org.springframework.ai.transformer.splitter.TokenTextSplitter;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
@Configuration
|
||||||
|
public class RagConfig {
|
||||||
|
@Value("${document.chunk-size}")
|
||||||
|
private int chunkSize;
|
||||||
|
|
||||||
|
@Value("${document.min-chunk-size}")
|
||||||
|
private int minChunkSize;
|
||||||
|
|
||||||
|
@Value("${document.max-num-chunk}")
|
||||||
|
private int maxNumChunk;
|
||||||
|
@Bean
|
||||||
|
public TokenTextSplitter tokenTextSplitter() {
|
||||||
|
return new TokenTextSplitter(
|
||||||
|
chunkSize,
|
||||||
|
minChunkSize,
|
||||||
|
5,
|
||||||
|
maxNumChunk,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
31
src/main/java/com/demo/controller/DocumentController.java
Normal file
31
src/main/java/com/demo/controller/DocumentController.java
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package com.demo.controller;
|
||||||
|
|
||||||
|
import com.demo.service.DocumentService;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("api/documents")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class DocumentController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public final DocumentService documentService;
|
||||||
|
|
||||||
|
@GetMapping("import")
|
||||||
|
public String importDocument() {
|
||||||
|
try {
|
||||||
|
documentService.importDocument();
|
||||||
|
} catch (IOException e) {
|
||||||
|
return "not ok" + e.getMessage();
|
||||||
|
}
|
||||||
|
return "ok";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
82
src/main/java/com/demo/service/DocumentService.java
Normal file
82
src/main/java/com/demo/service/DocumentService.java
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
package com.demo.service;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.ai.document.Document;
|
||||||
|
import org.springframework.ai.reader.TextReader;
|
||||||
|
import org.springframework.ai.transformer.splitter.TokenTextSplitter;
|
||||||
|
import org.springframework.ai.vectorstore.VectorStore;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.core.io.FileSystemResource;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
|
||||||
|
public class DocumentService {
|
||||||
|
|
||||||
|
@Value("${document.data-path}")
|
||||||
|
private String dataPath;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private final VectorStore vectorStore;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private final TokenTextSplitter textSplitter;
|
||||||
|
|
||||||
|
public void importDocument() throws IOException {
|
||||||
|
log.info("开始导入文档到向量数据库");
|
||||||
|
|
||||||
|
Path path = Paths.get(dataPath);
|
||||||
|
if (Files.notExists(path)) {
|
||||||
|
log.error("数据不存在:{}",dataPath);
|
||||||
|
throw new IOException("数据不存在:" + dataPath);
|
||||||
|
}
|
||||||
|
List<Document> allDocuments = new ArrayList<>();
|
||||||
|
// 读取文件
|
||||||
|
|
||||||
|
try (Stream<Path> paths = Files.walk(path)){
|
||||||
|
paths.filter(Files::isRegularFile)
|
||||||
|
.filter(p -> p.getFileName().toString().endsWith(".md")
|
||||||
|
|| p.getFileName().toString().endsWith(".txt"))
|
||||||
|
.forEach(filePath -> {
|
||||||
|
try {
|
||||||
|
log.info("开始处理 {} 文件",filePath);
|
||||||
|
TextReader reader = new TextReader(new FileSystemResource(filePath.toFile()));
|
||||||
|
List<Document> documents = reader.get();
|
||||||
|
|
||||||
|
// 切割文件。生成documents
|
||||||
|
List<Document> splitDocuments = textSplitter.apply(documents);
|
||||||
|
|
||||||
|
// 添加文件元信息
|
||||||
|
splitDocuments.forEach(document -> {
|
||||||
|
document.getMetadata().put("source",filePath.getFileName().toString());
|
||||||
|
document.getMetadata().put("file_path",filePath.toString());
|
||||||
|
});
|
||||||
|
allDocuments.addAll(splitDocuments);
|
||||||
|
|
||||||
|
log.info("文件{}分割为{}个文档片段",filePath.getFileName().toString(),splitDocuments.size());
|
||||||
|
}catch (Exception e) {
|
||||||
|
log.error("处理失败",e);
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allDocuments.size() > 0) {
|
||||||
|
log.info("开始往向量数据库中插入数据(通过embedding模型进行向量化),总共有{}个文档片源",allDocuments.size());
|
||||||
|
// 插入到向量数据库中
|
||||||
|
vectorStore.add(allDocuments);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -15,15 +15,28 @@ spring:
|
|||||||
# model: gemma4:e2b
|
# model: gemma4:e2b
|
||||||
# max-tokens: 10000
|
# max-tokens: 10000
|
||||||
temperature: 0.7
|
temperature: 0.7
|
||||||
# embedding:
|
embedding:
|
||||||
# api-key: ollama
|
api-key: key
|
||||||
# base-url: http://localhost:11434
|
base-url: https://api.siliconflow.cn
|
||||||
|
options:
|
||||||
|
model: BAAI/bge-large-zh-v1.5
|
||||||
|
dimensions: 1024
|
||||||
|
enable: true
|
||||||
|
vectorstore:
|
||||||
|
milvus:
|
||||||
|
client:
|
||||||
|
host: "192.168.50.103"
|
||||||
|
port: 19530
|
||||||
|
databaseName: "doris_docs"
|
||||||
|
collectionName: "vector_store"
|
||||||
|
embeddingDimension: 1024
|
||||||
|
indexType: IVF_FLAT
|
||||||
|
metricType: COSINE
|
||||||
|
# 增加这个配置,可以让springai帮我们创建vector_store
|
||||||
|
initialize-schema: true
|
||||||
|
|
||||||
#spring:
|
document:
|
||||||
# ai:
|
data-path: data
|
||||||
# ollama:
|
chunk-size: 400
|
||||||
# base-url: http://localhost:11434
|
min-chunk-size: 200
|
||||||
# chat:
|
max-num-chunk: 10000
|
||||||
# options:
|
|
||||||
# model: gemma4:e2b
|
|
||||||
# temperature: 0.7
|
|
||||||
Loading…
Reference in New Issue
Block a user