状态:✅ Lab 05 已完成
对话 持久化、多会话管理、上下文加载。
| 概念 | 一句话 |
|---|---|
| session | 一次独立对话的容器(标题、provider、时间) |
| message | 单条 UIMessage(role + parts JSON) |
| 深链接 | ?session=<uuid> 刷新后恢复当前会话 |
| history 截断 | 加载历史时按 token 预算裁剪(本 Lab 未实现) |
sessions(id, title, provider, created_at, updated_at)
messages(id, session_id, role, parts, created_at)parts存完整UIMessage.partsJSON,兼容 tool calling UI- 删除 session 级联删除 messages(
ON DELETE CASCADE)
- sessions:面向 UI 列表的元数据,按
updated_at排序 - messages:面向 LLM 的完整对话记录,按
created_at升序加载 - 一条 assistant 消息可含多个 part(text + tool-*)
本 Lab 全量加载。生产环境常见策略:
- 只取最近 N 条消息
- 滑动窗口 + 摘要旧对话
- 向量检索相关历史片段(RAG on history)
| API | 用途 |
|---|---|
POST /api/sessions |
新建空会话 |
GET /api/sessions |
左侧列表 |
GET /api/sessions/[id]/messages |
切换会话时加载历史 |
POST /api/chat |
带 sessionId 发消息并持久化 |
// 服务端:流结束后写 assistant
return createUIMessageStreamResponse({
stream: toUIMessageStream({
stream: result.stream,
originalMessages: messages,
onEnd: async ({ responseMessage }) => {
saveMessage(sessionId, responseMessage)
},
}),
})
// 客户端:切换会话
useEffect(() => {
fetch(`/api/sessions/${sessionId}/messages`)
.then(r => r.json())
.then(d => setMessages(d.messages))
}, [sessionId])- SQLite
sessions+messages表 - 刷新后历史仍在
- 左侧会话列表,新建 / 切换 / 删除