一个支持多模型切换、深度思考、联网搜索、知识库检索的 AI 聊天平台,前端 Vue3 + 后端 Node.js/Express,开箱即用。
🚀 核心功能
🤖 AI 对话
| 功能 | 说明 |
|---|
| 多模型切换 | 内置 DeepSeek V4 Pro / V3、GPT-4o,支持自定义服务商(中转站、Ollama 等),可视化配置页实时管理 |
| 流式输出 | SSE 实时推送,80ms 批量渲染引擎,大段代码不卡顿 |
| 深度思考 | DeepSeek 思维链模式,reasoning_effort=max,思考过程可折叠查看 |
| 联网搜索 | 一键开启,Tavily API 实时搜索最新信息辅助回答,5 秒超时保护 |
| 智能天气 | 开启搜索后,天气问题自动调高德 API,返回实时 + 未来几天预报 |
| 知识库 RAG | 本地文档(.txt .md .csv)拖入即用,启动时自动切片 + BGE-small 向量化 + LanceDB 存储,命中后气泡顶部显示 📚 来源标签 |
💬 会话管理
- 侧边栏会话列表,支持分页加载、右键重命名/删除
- 多轮对话完整上下文记忆,刷新浏览器不丢失
- 点击历史会话自动回显消息记录
🔧 模型配置(管理员)
ModelSelect 组件 + /settings 可视化配置页
- 增删改模型服务商:API 地址、Token、系统提示词、单价,实时生效
- 权限控制,仅管理员可见
🔐 认证系统
- 邮箱验证码注册/登录(Mock 模式)
- JWT Token 认证,24h 有效期
- Pinia + persist 状态持久化,刷新不丢登录
📱 移动端适配
- 侧边栏在 768px 以下自动变为抽屉悬浮层,带半透明遮罩,点击背景收起
- 对话页面宽度自适应,输入框不被挤压
🏗️ 技术架构
前端技术栈
| 层面 | 技术 | 版本 |
|---|
| 框架 | Vue 3 Composition API | 3.5 |
| 语言 | TypeScript | 5.8 |
| 构建 | Vite | 6.0 |
| UI 库 | Element Plus | 2.10 |
| AI 组件 | vue-element-plus-x | 1.3 |
| CSS | UnoCSS + SCSS | 66.3 |
| 状态管理 | Pinia + persist | 3.0 |
| 路由 | Vue Router | 4 |
| HTTP | hook-fetch(SSE 流式) | 2.0 |
后端技术栈
| 层面 | 技术 |
|---|
| 运行时 | Node.js + Express + TypeScript |
| 数据库 | SQLite(sql.js WASM,零安装零配置) |
| AI 引擎 | LangChain + OpenAI SDK 双通道 |
| 向量库 | LanceDB(纯 Node.js 嵌入式,零外部依赖) |
| Embedding | BGE-small-zh-v1.5(本地 CPU 免费) |
| 认证 | bcryptjs + jsonwebtoken |
| 校验 | Zod Schema 全接口覆盖 |
📂 项目结构
ruoyi-element-ai/
├── src/ # 前端源码
│ ├── api/ # API 接口层(auth/chat/model/session)
│ ├── assets/ # 静态资源(Remix Icon SVG × 1120+)
│ ├── components/ # 公共组件
│ │ ├── DeepThinking/ # 深度思考开关
│ │ ├── LoginDialog/ # 登录弹窗(账号密码/二维码/注册)
│ │ ├── ModelSelect/ # 模型选择下拉
│ │ ├── Popover/ # 通用弹出层(基于 @floating-ui/vue)
│ │ └── SvgIcon/ # SVG 图标组件
│ ├── layouts/ # 布局系统
│ │ └── LayoutVertical/ # 桌面端纵向布局
│ │ ├── Aside/ # 侧边栏(会话列表 + 新对话)
│ │ └── Header/ # 顶部栏(折叠 + 头像弹窗菜单)
│ ├── pages/ # 页面
│ │ ├── chat/ # 聊天页(默认页 + 对话页)
│ │ ├── settings/ # 模型配置页(管理员)
│ │ └── error/ # 403/404 错误页
│ ├── routers/ # Vue Router 路由配置
│ ├── stores/ # Pinia 状态管理(8 个模块)
│ ├── styles/ # 全局样式(GitHub Markdown 渲染等)
│ └── utils/ # 工具函数(hook-fetch 封装)
│
├── server/ # 后端源码
│ ├── src/
│ │ ├── db/ # 数据库层(repo 模式)
│ │ │ ├── connection.ts # 建表 + 种子数据
│ │ │ ├── utils.ts # snake_case → camelCase 转换
│ │ │ └── repo/ # user/session/message/model CRUD
│ │ ├── routes/ # Express 路由
│ │ ├── services/ # 业务逻辑
│ │ │ ├── chat.ts # LangChain + OpenAI SDK 流式对话
│ │ │ ├── search.ts # Tavily 联网搜索(5s 超时)
│ │ │ ├── weather.ts # 高德天气 API
│ │ │ └── rag.ts # 文档加载→切片→BGE 向量化→LanceDB 检索
│ │ ├── middleware/ # JWT 认证中间件
│ │ └── validation/ # Zod Schema 全接口校验
│ ├── documents/ # 知识库文件目录
│ ├── API.md # 后端接口文档
│ └── Dockerfile # Docker 部署支持
│
├── ARCHITECTURE.md # 本文档
├── vite.config.mts # Vite 配置
├── uno.config.ts # UnoCSS 配置
└── package.json # 前端依赖
🔄 数据流
用户操作 → 组件 dispatch → Pinia Store → API 调用 → 后端
↓
SSE 流式响应 ← hook-fetch stream() ← POST /chat/send ←┘
↓
handleDataChunk() → 80ms 批量缓冲 → bubbleItems.content → XMarkdown 渲染
核心 Store
| Store | 管理状态 | 是否持久化 |
|---|
userStore | token、userInfo、登录弹框 | ✅ |
sessionStore | 会话列表、分页、CRUD、当前会话 | ❌ |
chatStore | chatMap(消息缓存)、深度思考开关 | ❌ |
modelStore | 模型列表、当前选中模型 | ❌ |
designStore | 主题色、折叠状态、布局模式、暗黑模式 | ✅ |
🌐 路由设计
| 路径 | 名称 | 页面 | 说明 |
|---|
/ | - | redirect → /chat | 根路径重定向 |
/chat | chat | 默认聊天页 | 欢迎文字 + 输入框 + 模型选择 |
/chat/:id | chatWithId | 对话页 | 消息列表 + SSE 流式 + 思维链面板 |
/settings | settings | 模型配置页 | 仅管理员可见(beforeEnter 守卫) |
/403 | 403 | 禁止访问 | |
/404 | 404 | 页面不存在 | |
🔌 后端 API 总览
| 方法 | 路径 | 功能 | 认证 |
|---|
| POST | /auth/login | 登录 → JWT | ❌ |
| POST | /auth/register | 邮箱注册 | ❌ |
| POST | /resource/email/code | 验证码(Mock) | ❌ |
| POST | /chat/send | AI 流式对话(SSE) | ✅ |
| GET | /system/model/modelList | 模型列表 | ✅ |
| POST | /system/model | 新增模型 | ✅ |
| PUT | /system/model/:id | 更新模型 | ✅ |
| GET | /system/session/list | 会话列表(分页) | ✅ |
| POST | /system/session | 创建会话 | ✅ |
| PUT | /system/session | 更新会话 | ✅ |
| GET | /system/session/:id | 会话详情 | ✅ |
| DELETE | /system/session/:ids | 删除会话 | ✅ |
| POST | /system/message | 保存消息 | ✅ |
| GET | /system/message/list | 消息列表 | ✅ |
🔍 知识库检索流程
server/documents/ ← 拖入 .txt .md .csv
↓ 启动时
加载 → 切片(400字/150重叠) → BGE-small 向量化 → LanceDB 落盘
↓ 运行时
用户提问 → BGE 向量化 → LanceDB 相似检索 → 注入 system prompt → AI 回答
检索优先级:知识库 > 天气 > Tavily 联网搜索
🛠️ 环境变量
前端
| 变量 | 开发环境 | 生产环境 |
|---|
VITE_API_URL | /dev-api | /prod-api |
VITE_PROXY_TARGET | http://localhost:3000 | - |
后端
| 变量 | 说明 |
|---|
PORT | 服务端口,默认 3000 |
JWT_SECRET | JWT 签名密钥 |
OPENAI_API_KEY | OpenAI API Key(兜底) |
TAVILY_API_KEY | Tavily 联网搜索 Key |
AMAP_KEY | 高德天气 API Key |
LANCEDB_PATH | LanceDB 向量库路径 |
🚢 部署
本地开发
# 后端
cd server && pnpm dev
# 前端
pnpm dev
生产部署
# 前端构建
pnpm build # 输出到 dist/
# 后端
cd server && pnpm build # 编译到 dist/
pm2 start dist/index.js --name ruoyi-ai
# Nginx(前端 + API 反代)
# 前端静态文件指向 dist/,/prod-api/ 代理到 localhost:3000
Docker
cd server
docker build -t ruoyi-ai-server .
docker run -d --name ruoyi-ai -p 3000:3000 -v $(pwd)/data.db:/app/data.db ruoyi-ai-server
📄 License
MIT © huaiji123