AI 助手功能 - 需求规格说明书
| 文档版本 |
修订日期 |
修订人 |
修订内容 |
| V1.0 |
2026-05-23 |
— |
初始版本,定义首页 AI 助手聊天功能需求 |
| V1.1 |
2026-05-23 |
— |
增加多轮上下文(最多 5 轮/会话)、会话持久化、左侧历史会话列表与回看能力 |
| V1.2 |
2026-05-23 |
— |
产品约定(D-01~D-06)经确认纳入正式需求,移除待确认表述 |
1. 项目概述
1.1 功能背景
当前 Jog 博客系统公开站点顶部导航(BlogLayout)仅提供 「首页」 入口。访客与登录用户无法在站内直接获得与博客、写作相关的智能问答能力。为提升站点互动性与 AI 能力曝光,在首页导航区新增 「AI 助手」 入口,提供独立的对话页面:用户可 多轮追问(单会话最多 5 轮),问答内容 持久化存储;页面 左侧展示历史会话,点选可 完整回看 当时的全部提问与 AI 回复。
1.2 功能目标
- 在公开站点顶部导航增加「AI 助手」入口,与「首页」并列,便于发现与访问
- 支持 多轮上下文对话(单会话最多 5 轮),超出后引导用户 新建会话 继续提问
- 持久化 用户每条提问与 AI 每条回复,刷新或换设备登录后可恢复历史
- 页面 左侧会话列表 + 右侧对话区,点选历史会话可只读回看完整往来记录
- 复用现有 DashScope(阿里云百炼)OpenAI 兼容接入与
dashscope.* 配置
- 通过登录鉴权与用户级限流,控制调用成本与滥用风险
1.3 适用范围
| 角色 |
涉及范围 |
| 产品经理 |
验证导航、多轮上限、新会话流程、左侧历史与回看交互 |
| 前端开发工程师 |
左右分栏布局、会话列表、多轮发送、新会话、历史回看 |
| 后端开发工程师 |
对话 API、会话/消息持久化、多轮上下文组装、Flyway 表结构 |
| 测试工程师 |
多轮边界、持久化、历史加载、5 轮上限等用例 |
| 运维工程师 |
复用 DASHSCOPE_API_KEY;关注对话表容量与备份策略 |
1.4 现状说明
| 项目 |
现状 |
| 顶部导航 |
jog-frontend/src/layouts/BlogLayout.vue 中 el-menu 仅含「首页」 |
| 路由 |
公开布局子路由仅有 / 与 /article/:id |
| AI 能力 |
已有摘要、润色等 /api/app/** 接口,均依赖 DashScope |
| 数据存储 |
尚无 AI 对话相关表,需新增 Flyway 迁移 |
1.5 改动合理性评估(V1.1)
| 改动项 |
合理性说明 |
| 多轮 + 最多 5 轮 |
满足追问与指代理解;限制轮次可控制 Token 成本与模型超时风险,与现有 AI 功能限流思路一致 |
| 问答持久化 |
与「左侧历史、完整回看」强依赖;需登录态绑定 user_id,避免数据串户 |
| 左侧历史列表 |
常见聊天产品形态;列表按 会话 聚合(见 2 名词解释),避免每条提问占一行导致列表过长 |
| 新会话 |
5 轮上限后的自然出口;同时用于用户主动开启新话题 |
2. 名词解释
| 术语 |
说明 |
| AI 助手 |
面向站点用户的通用问答对话功能 |
| 会话(Session) |
一次连续对话线程,拥有唯一 sessionId;左侧历史列表的 每一行对应一个会话 |
| 轮次(Round) |
1 轮 = 1 条用户提问 + 1 条 AI 回复(均成功落库后计 1 轮);单会话最多 5 轮 |
| 新会话 |
用户主动点击「新会话」,创建新的 sessionId,右侧对话区清空,轮次计数从 0 开始 |
| 只读回看 |
从左侧点选 已满 5 轮 的会话,或用户仅查看历史时:展示完整消息记录,不可再发送 |
| 继续对话 |
点选 未满 5 轮 的历史会话时:加载历史消息,可在该 sessionId 下继续追问 |
| 会话标题 |
列表展示用,默认取该会话 首条用户提问 前 30 字(超出以 … 结尾) |
| DashScope |
阿里云百炼 API,本系统通过 OpenAI 兼容 chat/completions 调用 |
3. 功能需求清单
3.1 导航入口(前端)
(与 V1.0 一致,编号保留。)
3.1.2 业务规则
| 编号 |
规则项 |
业务规则说明 |
| FR-AI-CHAT-NAV-01 |
按钮位置 |
位于 BlogLayout 顶部 el-menu 内,紧挨「首页」之后,文案为「AI 助手」 |
| FR-AI-CHAT-NAV-02 |
路由 |
跳转 /ai-assistant,路由 name 建议 AiAssistant,页面标题「AI 助手」 |
| FR-AI-CHAT-NAV-03 |
激活态 |
当前路由为 /ai-assistant 时菜单项高亮 |
| FR-AI-CHAT-NAV-04 |
可见性 |
未登录可见入口;发送消息、查看历史列表 需登录(见 3.2) |
| FR-AI-CHAT-NAV-05 |
样式 |
与「首页」一致,可选聊天图标 |
3.1.3 验收标准
| 编号 |
验证场景 |
预期结果 |
| AC-AI-CHAT-NAV-01 |
任意公开页查看顶部导航 |
可见「首页」与「AI 助手」 |
| AC-AI-CHAT-NAV-02 |
点击「AI 助手」 |
进入 /ai-assistant |
| AC-AI-CHAT-NAV-03 |
在 AI 助手页刷新 |
「AI 助手」为激活态 |
3.2 AI 助手对话页(前端)
3.2.1 功能描述
新增 AiAssistant.vue(BlogLayout 子路由)。页面为 左右分栏:
- 左侧(约 260px):顶部「新会话」按钮 + 当前用户的 历史会话列表(按最近更新时间倒序)
- 右侧:当前会话的 完整消息流(用户/AI 气泡)+ 底部输入区与「发送」;显示当前会话 轮次指示(如
3/5)
用户发送问题时携带当前 sessionId(新会话时由后端创建或前端先调创建接口获得)。成功后消息入库并在右侧追加。左侧列表在首条提问成功后出现/更新该会话项。
3.2.2 页面布局
3.2.3 业务规则
| 编号 |
规则项 |
业务规则说明 |
| FR-AI-CHAT-FE-01 |
分栏布局 |
左侧固定宽约 260px,右侧 flex:1;小屏(<768px)可折叠左侧为抽屉(可选,首版允许左右同时展示并横向滚动) |
| FR-AI-CHAT-FE-02 |
新会话按钮 |
左侧顶部主按钮「新会话」;点击后:清空右侧消息、清空当前 sessionId、轮次显示 0/5、输入区可用;不删除 已有历史会话 |
| FR-AI-CHAT-FE-03 |
历史列表项 |
展示会话标题(首问前 30 字)+ 最后更新时间;当前选中会话高亮;默认进入页面时选中 最近一次活跃会话(若无则空状态) |
| FR-AI-CHAT-FE-04 |
点选历史 |
调用 GET .../sessions/{id}/messages 加载 该会话全部消息(按时间正序),右侧完整展示用户提问与 AI 回复全文 |
| FR-AI-CHAT-FE-05 |
继续 vs 只读 |
若该会话 roundCount < 5:加载后可继续发送(sessionId 设为当前);若 roundCount >= 5:只读回看,输入区禁用,展示提示条 |
| FR-AI-CHAT-FE-06 |
五轮上限提示 |
当前会话已达 5 轮时:禁用发送;提示「当前会话已满 5 轮,请点击左侧 新会话 开始新的对话」;ElMessage.warning 可选 |
| FR-AI-CHAT-FE-07 |
轮次指示 |
右侧标题栏展示 当前轮次/5(仅统计已成功完成的 user+assistant 一对) |
| FR-AI-CHAT-FE-08 |
输入框 |
textarea,占位符「请输入您的问题…」,1~6 行自适应 |
| FR-AI-CHAT-FE-09 |
发送 |
主按钮「发送」;Ctrl/Cmd+Enter 发送;trim 后 1~2000 字符 |
| FR-AI-CHAT-FE-10 |
登录校验 |
未登录:左侧列表为空或展示「登录后查看历史」;发送时提示并跳转 /login?redirect=/ai-assistant |
| FR-AI-CHAT-FE-11 |
Loading |
请求中发送按钮 loading、输入只读;列表末「正在思考…」 |
| FR-AI-CHAT-FE-12 |
消息展示 |
用户/AI 分色气泡;AI 文本 pre-wrap;首版不做 Markdown |
| FR-AI-CHAT-FE-13 |
失败处理 |
若 AI 调用失败:不 将本轮计入 roundCount;用户消息可保留为「发送失败」状态或允许重试(见 3.3 FR-AI-CHAT-BE-15) |
| FR-AI-CHAT-FE-14 |
刷新恢复 |
刷新页面后重新拉取会话列表与当前/最近会话消息,不依赖 localStorage 存对话正文 |
| FR-AI-CHAT-FE-15 |
空状态 |
无会话时右侧展示欢迎文案;左侧列表空状态「暂无对话,点击新会话开始」 |
| FR-AI-CHAT-FE-16 |
列表分页 |
会话列表默认加载最近 50 条,底部「加载更多」分页(page/size) |
| FR-AI-CHAT-FE-17 |
滚动 |
右侧消息区内部滚动;新消息后滚到底部;回看历史会话打开时滚到底部 |
3.2.4 验收标准
| 编号 |
验证场景 |
预期结果 |
| AC-AI-CHAT-FE-01 |
已登录,点击「新会话」后连续问答 3 次 |
右侧 3 组问答,指示 3/5,左侧出现 1 个会话项 |
| AC-AI-CHAT-FE-02 |
当前会话第 5 轮成功后尝试第 6 次发送 |
发送被拦截,提示点击「新会话」 |
| AC-AI-CHAT-FE-03 |
点击「新会话」后再提问 |
新会话独立入库,左侧新增或切换到新会话项 |
| AC-AI-CHAT-FE-04 |
点选已满 5 轮的历史会话 |
完整展示 5 轮共 10 条消息,输入区禁用,提示只读 |
| AC-AI-CHAT-FE-05 |
点选仅 2 轮的历史会话并继续提问 |
加载 2 轮历史后继续,第 3 轮成功后为 3/5 |
| AC-AI-CHAT-FE-06 |
刷新页面 |
会话列表与最近会话消息与刷新前一致 |
| AC-AI-CHAT-FE-07 |
未登录进入页面 |
无法发送;引导登录 |
3.3 AI 对话与会话接口(后端)
3.3.1 功能描述
提供会话管理与多轮对话能力:
- 创建/继续会话并发送消息(调用大模型时带入 当前会话已成功落库的全部历史,最多 5 轮 = 10 条消息)
- 查询当前用户会话列表
- 查询指定会话下的全部消息(供左侧点选回看)
所有问答 写入数据库;仅允许操作 当前登录用户 自己的会话。
3.3.2 数据模型(Flyway)
建议新增迁移 V5__ai_chat_tables.sql(版本号以仓库实际递增为准):
表 ai_chat_session
| 字段 |
类型 |
说明 |
| id |
BIGINT PK |
会话 ID |
| user_id |
BIGINT |
所属用户,索引 |
| title |
VARCHAR(64) |
会话标题,首条用户消息截断 |
| round_count |
TINYINT |
已完成轮次,0~5 |
| last_message_at |
DATETIME |
最后一条消息时间,列表排序用 |
| created_at |
DATETIME |
创建时间 |
| updated_at |
DATETIME |
更新时间 |
| deleted |
TINYINT |
逻辑删除,默认 0(与项目 @TableLogic 一致) |
表 ai_chat_message
| 字段 |
类型 |
说明 |
| id |
BIGINT PK |
消息 ID |
| session_id |
BIGINT |
外键 → ai_chat_session.id |
| role |
VARCHAR(16) |
user / assistant |
| content |
TEXT |
提问或回复 全文 |
| sort_order |
INT |
会话内顺序,从 1 递增 |
| created_at |
DATETIME |
创建时间 |
3.3.3 接口清单
| 方法 |
路径 |
说明 |
| POST |
/api/app/ai/sessions |
创建空会话,返回 sessionId |
| GET |
/api/app/ai/sessions |
分页查询当前用户会话列表 |
| GET |
/api/app/ai/sessions/{sessionId}/messages |
查询会话全部消息(正序) |
| POST |
/api/app/ai/chat |
在指定会话中发送用户消息并返回 AI 回复 |
3.3.4 发送消息接口 POST /api/app/ai/chat
请求体
| 字段 |
必填 |
说明 |
| sessionId |
是 |
会话 ID;须属于当前用户且 round_count < 5 |
| message |
是 |
本条用户提问,1~2000 字符(trim 后) |
处理流程
- 校验登录、
sessionId 归属、round_count < 5、message 合法
- 插入
ai_chat_message(role=user)
- 读取该会话已有消息(最多 5 轮历史),按
sort_order 组装 messages 数组送入 DashScope(含 System Prompt)
- 调用模型,得到
reply
- 插入
ai_chat_message(role=assistant,content=全文)
- 更新
session.round_count += 1、last_message_at;若为首条用户消息则更新 title
- 返回
reply 及更新后的 roundCount
响应 data 示例
3.3.5 业务规则
| 编号 |
规则项 |
业务规则说明 |
| FR-AI-CHAT-BE-01 |
鉴权 |
全部接口需登录;sessionId 必须属于当前 userId,否则 403 或 404 |
| FR-AI-CHAT-BE-02 |
轮次上限 |
round_count >= 5 时拒绝 POST /chat,返回 400,message:「当前会话已满 5 轮,请新建会话」 |
| FR-AI-CHAT-BE-03 |
多轮上下文 |
调用模型时传入:System Prompt + 该会话已落库的 user/assistant 消息(按时间序),最多 10 条(5 轮);不含本次尚未入库的 user 消息则先入库 user 再调模型 |
| FR-AI-CHAT-BE-04 |
上下文长度保护 |
组装后的总字符数超过 dashscope.max-input(默认 8000)时,从最早的用户/助手对开始丢弃,直至不超限(System 与当前 user 消息保留) |
| FR-AI-CHAT-BE-05 |
存储 |
用户 message 与 AI reply 全文 写入 ai_chat_message.content,供历史回看 |
| FR-AI-CHAT-BE-06 |
会话列表 |
GET /sessions 按 last_message_at 降序;返回 id, title, roundCount, lastMessageAt;默认 size=50 |
| FR-AI-CHAT-BE-07 |
消息列表 |
GET /sessions/{id}/messages 返回 id, role, content, sortOrder, createdAt 全量正序 |
| FR-AI-CHAT-BE-08 |
新会话 |
POST /sessions 创建 round_count=0 的记录;前端「新会话」优先调此接口拿到 sessionId 再提问 |
| FR-AI-CHAT-BE-09 |
模型与 Key |
复用 DashScopeProperties;Key 缺失返回既有 AI_API_KEY_MISSING |
| FR-AI-CHAT-BE-10 |
System Prompt |
与 V1.0 一致,并补充:「当前为同一会话的多轮对话,请结合上文回答,避免重复已说过的内容。」 |
| FR-AI-CHAT-BE-11 |
回复截断 |
单条 reply 超过 4000 字符截断并 … |
| FR-AI-CHAT-BE-12 |
超时/限流/异常 |
超时 30s → 5002;用户每分钟最多 10 次 POST /chat(Redis ai_chat:rate:);DashScope 失败 → 5001 |
| FR-AI-CHAT-BE-13 |
日志 |
日志中 不打印 问答全文,可记录 sessionId、轮次、字符长度、token、耗时 |
| FR-AI-CHAT-BE-14 |
软删除 |
会话表支持逻辑删除(为后续「删除历史」预留);首版前端 不提供 删除入口 |
| FR-AI-CHAT-BE-15 |
失败不落 assistant |
模型调用失败时:已插入的 user 消息 保留;不插入 assistant、不增加 round_count;返回错误码,前端允许用户 重试发送(同 sessionId 不重复插 user,或后端按幂等键去重——首版允许重复 user 消息则需在需求中禁止,采用:失败时仅重试模型,不重复插入 user) |
FR-AI-CHAT-BE-15 实现约定:发送接口在步骤 2 插入 user 后若模型失败,user 消息保留;重试时若上一条为未配对的 user,则 不再插入新 user,仅重新请求模型并写入 assistant。
3.3.6 错误码补充
| 错误码 / HTTP |
描述 |
触发条件 |
| 400 |
参数错误 |
message 非法 |
| 400 |
会话轮次已满 |
round_count >= 5 |
| 403/404 |
会话不存在或无权访问 |
sessionId 非本人 |
| 401 |
未登录 |
无 Token |
| 429 |
请求过于频繁 |
限流 |
| 5001/5002 |
AI 不可用 / 超时 |
DashScope 异常 |
3.3.7 验收标准
| 编号 |
验证场景 |
预期结果 |
| AC-AI-CHAT-BE-01 |
新会话连续 5 次成功 /chat |
round_count=5,第 6 次返回 400 |
| AC-AI-CHAT-BE-02 |
第 3 轮提问含指代「它」 |
模型请求体含前 2 轮共 4 条历史消息 |
| AC-AI-CHAT-BE-03 |
GET .../messages |
返回条数与轮次一致,content 为当时全文 |
| AC-AI-CHAT-BE-04 |
用户 A 访问用户 B 的 sessionId |
403/404 |
| AC-AI-CHAT-BE-05 |
模型失败后重试 |
不重复 user 行,成功后 round_count 正确 +1 |
3.4 配置与部署
仍复用 dashscope.* 与 DASHSCOPE_API_KEY。新增表由 Flyway 自动迁移。部署后验证:多轮对话、刷新恢复、第 5 轮后新建会话。
4. 交互流程
4.1 首次提问(新会话)
4.2 同会话多轮追问
4.3 回看历史会话
4.4 满 5 轮后继续提问
5. 接口与代码对齐(规划)
5.1 后端
| 模块 |
文件 |
变更说明 |
| jog-admin |
db/migration/V5__ai_chat_tables.sql |
会话与消息表 |
| jog-module-blog |
entity/AiChatSession.java, AiChatMessage.java |
实体 |
| jog-module-blog |
mapper/... |
MyBatis-Plus Mapper |
| jog-module-blog |
dto/*, vo/* |
请求/响应对象 |
| jog-module-blog |
service/AiChatService + impl |
多轮组装、持久化、DashScope 调用 |
| jog-module-blog |
controller/AiChatController.java |
上述 REST 接口 |
5.2 前端
| 模块 |
文件 |
变更说明 |
| jog-frontend |
layouts/BlogLayout.vue |
「AI 助手」导航 |
| jog-frontend |
router/index.js |
/ai-assistant |
| jog-frontend |
views/AiAssistant.vue |
左右分栏主页面 |
| jog-frontend |
components/AiChatSidebar.vue(可选拆分) |
左侧列表 + 新会话 |
| jog-frontend |
components/AiChatPanel.vue(可选拆分) |
右侧消息 + 输入 |
| jog-frontend |
api/aiChat.js |
会话与 chat API 封装 |
6. 非功能性需求
| 编号 |
类型 |
需求说明 |
| NFR-01 |
性能 |
95 分位 ≤ 15s;5 轮上下文受 max-input 截断保护 |
| NFR-02 |
可用性 |
AI 不可用时仍可回看已存历史;失败可重试当前轮 |
| NFR-03 |
安全性 |
会话严格按 user_id 隔离;API Key 不入库/日志/仓库;HTTPS 传输 |
| NFR-04 |
隐私 |
对话正文存业务库,仅本人可读;管理后台 不提供 查看他人工单(首版) |
| NFR-05 |
可扩展性 |
轮次上限、列表条数可配置化;预留流式 SSE、删除会话 |
| NFR-06 |
容量 |
首版会话列表 仅分页加载(默认每页 50 条),不设单用户数量硬上限,不自动删除 历史会话 |
| NFR-07 |
可观测性 |
记录 sessionId、轮次、耗时、token;日志不打印全文 |
7. 范围外(后续迭代)
| 项 |
说明 |
| 流式输出 |
SSE 逐字展示回复 |
| 删除会话 |
前端删除 + 逻辑删除接口 |
| 未登录试用 |
公开 API + IP 限流 |
| Markdown渲染 |
AI 回复富文本(需 XSS 防护) |
| 会话重命名 |
用户自定义左侧标题 |
| 导出对话 |
导出 Markdown/PDF |
8. 风险与缓解
| 风险 |
影响 |
缓解措施 |
| 5 轮上下文 Token 过大 |
超时/费用 |
max-input 截断最早轮次 |
| 历史表数据增长 |
存储成本 |
分页列表;后续归档策略 |
| 满 5 轮体验断裂 |
用户困惑 |
明确提示 +「新会话」一键 |
| 失败重试重复 user |
轮次与展示错乱 |
BE-15 幂等重试约定 |
9. 产品约定(已确认)
以下约定已于 2026-05-23 与产品方确认,作为 V1.1 正式需求的一部分,开发与测试须按此实现。
| 编号 |
约定项 |
需求说明 |
| D-01 |
左侧列表按 会话 聚合 |
每会话占列表一行;标题取首条用户提问前 30 字;点选后右侧展示该会话下 全部 问答全文(非按单条提问分行) |
| D-02 |
历史会话可继续对话 |
roundCount < 5 的会话:加载历史后 可继续发送;roundCount >= 5 的会话:只读回看,输入区禁用并引导「新会话」 |
| D-03 |
新会话不删除旧数据 |
点击「新会话」仅创建并切换至新 sessionId,清空右侧编辑区;不删除、不覆盖 已有会话数据 |
| D-04 |
首版不提供删除与重命名 |
前端无删除会话、无重命名入口;ai_chat_session.deleted 字段预留供后续迭代(见 §7) |
| D-05 |
失败不计轮、支持同轮重试 |
模型调用失败时不插入 assistant、不增加 round_count;允许对未配对的 user 消息重试,不重复插入 user(见 FR-AI-CHAT-BE-15) |
| D-06 |
进入页默认最近会话 |
已登录用户进入 /ai-assistant 时,默认选中 最近更新 的会话并加载其消息;无任何会话时展示空状态,等同待「新会话」 |
| D-07 |
会话保留策略 |
历史会话 仅分页展示(默认每页 50 条),不设 单用户数量硬上限,不自动删除 最旧会话(与 NFR-06 一致) |
编写人: AI 助手
评审人: 已确认(产品约定 D-01~D-07)
生效日期: 2026-05-23