All checks were successful
Java Maven 3.9.9 & JDK 26 CI/CD Pipeline / build-and-deploy (push) Successful in 9m30s
209 lines
6.8 KiB
Markdown
209 lines
6.8 KiB
Markdown
# Trace — 语音智能记账助手
|
||
|
||
基于语音识别的智能日常记账应用。按住说话即可完成事项录入与查询,由 DeepSeek 大模型理解意图并自动生成 SQL,实现"说话即记账"的流畅体验。
|
||
|
||
## 核心功能
|
||
|
||
| 功能 | 说明 |
|
||
|------|------|
|
||
| 🎤 **语音录入** | 按住麦克风说话,AI 自动提取时间、地点、金额、分类等信息并入库 |
|
||
| 🔍 **语音查询** | 用自然语言查询历史记录,如"我昨天花了多少钱"、"上次吃面是什么时候" |
|
||
| 💬 **智能聊天** | 支持闲聊交互,自动区分记账意图与普通对话 |
|
||
| 📋 **浏览筛选** | 按人物、时间、地点、分类多维度筛选查看所有事项,金额自动汇总 |
|
||
| 🔐 **登录认证** | Session 会话管理,首次启动自动创建默认用户 |
|
||
|
||
## 处理流程
|
||
|
||
```
|
||
用户语音 → [按住录音] → WAV 编码
|
||
→ MIMO ASR 语音识别 → 文本
|
||
→ DeepSeek LLM 意图分析
|
||
├── 录入意图 → 生成 INSERT SQL → 校验 → 入库
|
||
├── 查询意图 → Function Call 生成 SELECT SQL → 校验执行 → LLM 格式化回复
|
||
└── 聊天意图 → 直接回复
|
||
```
|
||
|
||
## 技术栈
|
||
|
||
| 层级 | 技术 |
|
||
|------|------|
|
||
| **框架** | Spring Boot 3.5.14 |
|
||
| **语言** | Java 26 |
|
||
| **ORM** | MyBatis-Plus 3.5.12 |
|
||
| **数据库** | MySQL 8.x |
|
||
| **模板引擎** | Thymeleaf |
|
||
| **前端** | Bootstrap 5.3 + 原生 JS(WAV 录音) |
|
||
| **LLM** | DeepSeek API(deepseek-v4-pro) |
|
||
| **ASR** | 小米 MIMO V2.5 ASR |
|
||
| **安全** | BCrypt 密码加密 + Session 认证 |
|
||
| **容器化** | Docker(多阶段构建) |
|
||
|
||
## 项目结构
|
||
|
||
```
|
||
src/main/java/com/l/trace/
|
||
├── TraceApplication.java # 应用主入口
|
||
├── config/
|
||
│ ├── DatabaseInitializer.java # 启动自动建表
|
||
│ ├── DeepSeekConfig.java # DeepSeek API 配置
|
||
│ ├── MimoAsrConfig.java # MIMO ASR API 配置
|
||
│ ├── MvcConfig.java # 拦截器注册
|
||
│ ├── MybatisPlusConfig.java # MyBatis-Plus 配置
|
||
│ └── SessionConfig.java # Session 会话配置
|
||
├── constant/
|
||
│ └── Constants.java # 系统常量
|
||
├── controller/
|
||
│ ├── AuthController.java # 登录/登出
|
||
│ ├── BrowseController.java # 条件筛选查询 API
|
||
│ ├── CommonController.java # 健康检查
|
||
│ ├── FilterController.java # 筛选选项 API
|
||
│ ├── PageController.java # 页面路由
|
||
│ └── VoiceController.java # 语音处理 API
|
||
├── dto/
|
||
│ ├── BrowseQuery.java # 浏览查询参数
|
||
│ ├── DeepSeekRequest.java # DeepSeek 请求体
|
||
│ ├── DeepSeekResponse.java # DeepSeek 响应体
|
||
│ ├── FilterOption.java # 筛选选项
|
||
│ └── VoiceResponse.java # 语音处理响应
|
||
├── entity/
|
||
│ ├── DailyRecord.java # 日常事项实体
|
||
│ ├── DistinctValue.java # 去重值实体
|
||
│ └── User.java # 用户实体
|
||
├── interceptor/
|
||
│ └── AuthInterceptor.java # 登录认证拦截器
|
||
├── mapper/
|
||
│ ├── DailyRecordMapper.java # 事项 Mapper
|
||
│ ├── DistinctValueMapper.java # 去重值 Mapper
|
||
│ └── UserMapper.java # 用户 Mapper
|
||
└── service/
|
||
├── AsrService.java # ASR 语音识别
|
||
├── AuthService.java # 认证服务
|
||
├── DistinctValueService.java # 去重值维护
|
||
├── LlmService.java # DeepSeek 交互
|
||
├── RecordService.java # 事项 CRUD
|
||
├── SqlValidationService.java # SQL 安全校验
|
||
└── VoiceService.java # 语音处理编排(核心)
|
||
```
|
||
|
||
## 数据库表
|
||
|
||
| 表名 | 说明 |
|
||
|------|------|
|
||
| `t_user` | 用户表,BCrypt 加密存储密码 |
|
||
| `t_daily_record` | 日常事项记录表(person, record_time, location, content, category, amount) |
|
||
| `t_distinct_value` | 筛选去重值表(field_name + field_value 唯一索引) |
|
||
|
||
建表脚本:`src/main/resources/schema.sql`,应用启动时自动执行。
|
||
|
||
## 快速开始
|
||
|
||
### 环境要求
|
||
|
||
- JDK 26
|
||
- Maven 3.9+
|
||
- MySQL 8.x
|
||
|
||
### 1. 配置数据库
|
||
|
||
创建 MySQL 数据库(应用会自动建表):
|
||
|
||
```sql
|
||
CREATE DATABASE IF NOT EXISTS trace DEFAULT CHARSET utf8mb4;
|
||
```
|
||
|
||
修改 `src/main/resources/application.yml` 中的数据库连接信息:
|
||
|
||
```yaml
|
||
spring:
|
||
datasource:
|
||
url: jdbc:mysql://your-host:3306/trace?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&createDatabaseIfNotExist=true
|
||
username: your-username
|
||
password: your-password
|
||
```
|
||
|
||
### 2. 配置 API Key
|
||
|
||
通过环境变量设置(推荐)或直接修改 `application.yml`:
|
||
|
||
```bash
|
||
# DeepSeek API Key
|
||
export DEEPSEEK_API_KEY=sk-your-key
|
||
|
||
# MIMO ASR API Key
|
||
export MIMO_API_KEY=sk-your-key
|
||
```
|
||
|
||
### 3. 启动应用
|
||
|
||
```bash
|
||
# 编译并运行
|
||
mvn spring-boot:run
|
||
|
||
# 或先打包再运行
|
||
mvn clean package -DskipTests
|
||
java -jar target/trace-1.0-SNAPSHOT.jar
|
||
```
|
||
|
||
### 4. 访问
|
||
|
||
打开浏览器访问 `http://localhost:8080`
|
||
|
||
- **默认用户名**: `admin`
|
||
- **默认密码**: `admin123`
|
||
|
||
## Docker 部署
|
||
|
||
```bash
|
||
# 构建镜像
|
||
docker build -t trace:latest .
|
||
|
||
# 运行容器
|
||
docker run -d \
|
||
-p 8080:8080 \
|
||
-e DEEPSEEK_API_KEY=sk-your-key \
|
||
-e MIMO_API_KEY=sk-your-key \
|
||
-e SPRING_DATASOURCE_URL=jdbc:mysql://your-host:3306/trace?... \
|
||
-e SPRING_DATASOURCE_USERNAME=root \
|
||
-e SPRING_DATASOURCE_PASSWORD=root \
|
||
--name trace \
|
||
trace:latest
|
||
```
|
||
|
||
## API 接口
|
||
|
||
| 路径 | 方法 | 说明 |
|
||
|------|------|------|
|
||
| `/` | GET | 主页(语音录入) |
|
||
| `/browse` | GET | 浏览筛选页 |
|
||
| `/login` | GET/POST | 登录页/登录请求 |
|
||
| `/logout` | GET | 登出 |
|
||
| `/hello` | GET | 健康检查 |
|
||
| `/api/voice/process` | POST | 上传音频,返回处理结果 |
|
||
| `/api/record/query` | POST | 条件筛选查询事项 |
|
||
| `/api/filter/options` | GET | 获取筛选下拉选项 |
|
||
|
||
## 配置项
|
||
|
||
| 配置路径 | 说明 | 默认值 |
|
||
|----------|------|--------|
|
||
| `server.port` | 服务端口 | `8080` |
|
||
| `deepseek.api-key` | DeepSeek API Key | 环境变量 `DEEPSEEK_API_KEY` |
|
||
| `deepseek.model` | DeepSeek 模型 | `deepseek-v4-pro` |
|
||
| `mimo.api-key` | MIMO ASR API Key | 环境变量 `MIMO_API_KEY` |
|
||
| `mimo.model` | ASR 模型 | `mimo-v2.5-asr` |
|
||
| `app.sql-max-retries` | SQL 生成失败最大重试次数 | `5` |
|
||
| `app.default-username` | 默认用户名 | `admin` |
|
||
| `app.default-password` | 默认密码 | `admin123` |
|
||
|
||
## 构建命令
|
||
|
||
```bash
|
||
mvn verify # 编译 + 测试
|
||
mvn compile # 仅编译
|
||
mvn test # 运行测试
|
||
mvn test -Dtest=MyTestClass # 运行单个测试类
|
||
mvn test -Dtest=MyTestClass#myMethod # 运行单个测试方法
|
||
mvn package # 打包 JAR
|
||
mvn clean # 清理
|
||
```
|