CHAT-000 P0 | ChatScope 里程碑总设计文档 #97

Closed
opened 2026-06-06 16:29:05 +08:00 by wangdl · 0 comments
Owner

一句话目标

所有 AI 会话都绑定明确 ChatScope。同一 scope 继续会话,不同 scope 打开或创建对应会话。前端所有入口必须显式传 scope,AI 页面不再猜上下文。


ChatScope 是什么

知习的 AI 对话不是普通聊天,而是学习对象绑定的上下文会话。每个会话必须明确知道自己在问谁。

type ChatScopeType =
  | "knowledge_base"   // 整个知识库
  | "folder"           // 某个分类/章节
  | "material"         // 某份资料
  | "knowledge_item"   // 某个知识点
  | "multi_source"     // 多个来源组合
  | "temporary_file"   // 临时上传文件
  | "global"           // 不绑定知识库的普通对话

核心规则

1. 会话必须绑定 scopeType + scopeId。
2. userId + scopeType + scopeId 完全一致,才允许继续上次会话。
3. scope 变化 → 打开或创建另一个 session,不修改当前 session。
4. 从知识点详情进入 → 必须 knowledge_item 会话,不能打开知识库会话。
5. 从资料详情/阅读页进入 → 必须 material 会话。
6. 从知识库详情进入 → 必须 knowledge_base 会话。
7. 手动新对话 → 在当前 scope 下新建会话。
8. 切换模型/深度思考/联网搜索 → 不改变 scope。

完整决策表

用户行为 当前会话 新目标 结果
从知识库详情点 AI 知识库 打开/创建知识库会话
从资料详情点 AI 资料 打开/创建资料会话
从阅读页点 AI 资料+位置 打开/创建资料会话
从知识点详情点 AI 知识点 打开/创建知识点会话
从分类页点 AI 分类 打开/创建分类会话
在知识库 A 会话切 B 知识库A 知识库B 打开/创建 B 会话
在资料 A 会话切资料 B 资料A 资料B 打开/创建 B 会话
在知识点会话切整个知识库 知识点 知识库 打开/创建知识库会话
在资料会话切整个知识库 资料 知识库 打开/创建知识库会话
手动点新对话 当前scope 当前scope 新建当前 scope 会话
切换模型 当前scope 当前scope 继续当前会话
开启深度思考 当前scope 当前scope 继续当前会话
删除会话 当前scope 删除聊天记录
删除知识点 知识点会话存在 知识点消失 会话标记来源已删除
删除资料 资料会话存在 资料消失 会话标记来源已删除
删除知识库 KB相关会话存在 KB消失 会话归档或删除

数据模型

ChatSession

model ChatSession {
  id                    String   @id @default(cuid())
  userId                String

  // Core scope fields
  scopeType             String   @default("knowledge_base")
  scopeId               String?
  parentKnowledgeBaseId String?
  parentMaterialId      String?
  parentFolderId        String?
  sourceIds             Json?    @default("[]")

  // Metadata
  createdFrom           String   @default("global_ai_entry")
  title                 String   @default("新对话")
  autoTitle             String?
  modelMode             String   @default("normal")
  modelId               String?
  isPinned              Boolean  @default(false)
  isArchived            Boolean  @default(false)
  isDeleted             Boolean  @default(false)

  lastMessageAt         DateTime?
  createdAt             DateTime @default(now())
  updatedAt             DateTime @updatedAt

  messages              ChatMessage[]
}

ChatScope 映射

scopeType scopeId parentKB 示例
knowledge_base kb.id = scopeId 问《计算机网络》
material material.id kb.id 问《数据库事务.pdf》
knowledge_item item.id kb.id 问”三次握手“
folder folder.id kb.id 问《TCP/IP》分类
global null null 普通对话

入口规则

每个入口显式传 ChatEntryContext

type ChatEntryContext = {
  scopeType: ChatScopeType
  scopeId: string | null
  parentKnowledgeBaseId?: string
  parentMaterialId?: string
  parentFolderId?: string
  createdFrom: string
  initialReadingPosition?: ReadingPosition
  initialPrompt?: string
}
入口 scopeType 传参
知识库底部 AI 对话 knowledge_base scopeId=kb.id, parentKB=kb.id
资料详情 AI 对话 material scopeId=material.id, parentKB=kb.id
资料阅读页 AI 对话 material +readingPosition
知识点详情 AI 对话 knowledge_item scopeId=item.id, parentKB=item.knowledgeBaseId
分类页 AI 对话 folder scopeId=folder.id, parentKB=kb.id

检索范围

不同 scope 的 loadContext 检索范围不同:

scopeType 检索内容
knowledge_base KB 下所有知识点 + 资料摘要(最多30条)
material 当前资料全文 + 关联知识点
knowledge_item 当前知识点 + 来源资料片段
folder 分类下资料 + 知识点
global 不检索知识库

顶层 API

POST /api/chat/sessions/open-or-create   ← 打开或创建 exact scope 会话
POST /api/chat/sessions                   ← 强制新建当前 scope 会话
GET  /api/chat/sessions                   ← 按 scope 过滤会话列表
GET  /api/chat/sessions/:id               ← 会话详情
DELETE /api/chat/sessions/:id             ← 软删除
PATCH /api/chat/sessions/:id              ← 仅 title/pinned/archived

open-or-create 请求体:

{
  "scopeType": "knowledge_item",
  "scopeId": "ki_123",
  "parentKnowledgeBaseId": "kb_001",
  "parentMaterialId": "mat_001",
  "createdFrom": "knowledge_item_detail"
}

响应:

{
  "sessionId": "chat_001",
  "isNew": false,
  "session": { ... }
}

子里程碑

编号 内容
M-CHAT-0 设计冻结与接口协议(#82 #83)
M-CHAT-1 后端数据模型与迁移(#79 #92 #93 #72 #73 #94)
M-CHAT-2 后端会话打开/创建逻辑(#81 #76 #85 #75 #84)
M-CHAT-3 后端消息发送与检索范围(#74 #86 #87 #88)
M-CHAT-4 iOS 入口改造(#39-#44 ios-projects)
M-CHAT-5 iOS AI 对话页 Scope 展示(#45-#50 ios-projects)
M-CHAT-6 会话列表与管理(#51-#54 ios-projects #95 #96)
M-CHAT-7 回归测试与旧数据兼容(#78 #89 #90 #91)

最小验收链路

1. 从知识库详情进入 AI → 打开 knowledge_base 会话 ✅
2. 从资料详情进入 AI → 打开 material 会话 ✅
3. 从知识点详情进入 AI → 打开 knowledge_item 会话 ✅
4. 在知识点会话切换到整个知识库 → 打开 knowledge_base 会话 ✅
5. 在知识库 A 切换到知识库 B → 打开 B 的会话,不复用 A ✅
6. 在当前 scope 下点新对话 → 创建同 scope 的新 session ✅

这 6 条跑通,ChatScope 系统才算真正收口。

## 一句话目标 **所有 AI 会话都绑定明确 ChatScope。同一 scope 继续会话,不同 scope 打开或创建对应会话。前端所有入口必须显式传 scope,AI 页面不再猜上下文。** --- ## ChatScope 是什么 知习的 AI 对话不是普通聊天,而是**学习对象绑定的上下文会话**。每个会话必须明确知道自己在问谁。 ```ts type ChatScopeType = | "knowledge_base" // 整个知识库 | "folder" // 某个分类/章节 | "material" // 某份资料 | "knowledge_item" // 某个知识点 | "multi_source" // 多个来源组合 | "temporary_file" // 临时上传文件 | "global" // 不绑定知识库的普通对话 ``` --- ## 核心规则 ```text 1. 会话必须绑定 scopeType + scopeId。 2. userId + scopeType + scopeId 完全一致,才允许继续上次会话。 3. scope 变化 → 打开或创建另一个 session,不修改当前 session。 4. 从知识点详情进入 → 必须 knowledge_item 会话,不能打开知识库会话。 5. 从资料详情/阅读页进入 → 必须 material 会话。 6. 从知识库详情进入 → 必须 knowledge_base 会话。 7. 手动新对话 → 在当前 scope 下新建会话。 8. 切换模型/深度思考/联网搜索 → 不改变 scope。 ``` --- ## 完整决策表 | 用户行为 | 当前会话 | 新目标 | 结果 | |---------|---------|-------|------| | 从知识库详情点 AI | 无 | 知识库 | 打开/创建知识库会话 | | 从资料详情点 AI | 无 | 资料 | 打开/创建资料会话 | | 从阅读页点 AI | 无 | 资料+位置 | 打开/创建资料会话 | | 从知识点详情点 AI | 无 | 知识点 | 打开/创建知识点会话 | | 从分类页点 AI | 无 | 分类 | 打开/创建分类会话 | | 在知识库 A 会话切 B | 知识库A | 知识库B | 打开/创建 B 会话 | | 在资料 A 会话切资料 B | 资料A | 资料B | 打开/创建 B 会话 | | 在知识点会话切整个知识库 | 知识点 | 知识库 | 打开/创建知识库会话 | | 在资料会话切整个知识库 | 资料 | 知识库 | 打开/创建知识库会话 | | 手动点新对话 | 当前scope | 当前scope | 新建当前 scope 会话 | | 切换模型 | 当前scope | 当前scope | 继续当前会话 | | 开启深度思考 | 当前scope | 当前scope | 继续当前会话 | | 删除会话 | 当前scope | 无 | 删除聊天记录 | | 删除知识点 | 知识点会话存在 | 知识点消失 | 会话标记来源已删除 | | 删除资料 | 资料会话存在 | 资料消失 | 会话标记来源已删除 | | 删除知识库 | KB相关会话存在 | KB消失 | 会话归档或删除 | --- ## 数据模型 ### ChatSession ```prisma model ChatSession { id String @id @default(cuid()) userId String // Core scope fields scopeType String @default("knowledge_base") scopeId String? parentKnowledgeBaseId String? parentMaterialId String? parentFolderId String? sourceIds Json? @default("[]") // Metadata createdFrom String @default("global_ai_entry") title String @default("新对话") autoTitle String? modelMode String @default("normal") modelId String? isPinned Boolean @default(false) isArchived Boolean @default(false) isDeleted Boolean @default(false) lastMessageAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt messages ChatMessage[] } ``` ### ChatScope 映射 | scopeType | scopeId | parentKB | 示例 | |-----------|---------|----------|------| | knowledge_base | kb.id | = scopeId | 问《计算机网络》 | | material | material.id | kb.id | 问《数据库事务.pdf》 | | knowledge_item | item.id | kb.id | 问”三次握手“ | | folder | folder.id | kb.id | 问《TCP/IP》分类 | | global | null | null | 普通对话 | --- ## 入口规则 每个入口显式传 `ChatEntryContext`: ```ts type ChatEntryContext = { scopeType: ChatScopeType scopeId: string | null parentKnowledgeBaseId?: string parentMaterialId?: string parentFolderId?: string createdFrom: string initialReadingPosition?: ReadingPosition initialPrompt?: string } ``` | 入口 | scopeType | 传参 | |------|-----------|------| | 知识库底部 AI 对话 | knowledge_base | scopeId=kb.id, parentKB=kb.id | | 资料详情 AI 对话 | material | scopeId=material.id, parentKB=kb.id | | 资料阅读页 AI 对话 | material | +readingPosition | | 知识点详情 AI 对话 | knowledge_item | scopeId=item.id, parentKB=item.knowledgeBaseId | | 分类页 AI 对话 | folder | scopeId=folder.id, parentKB=kb.id | --- ## 检索范围 不同 scope 的 `loadContext` 检索范围不同: | scopeType | 检索内容 | |-----------|---------| | knowledge_base | KB 下所有知识点 + 资料摘要(最多30条) | | material | 当前资料全文 + 关联知识点 | | knowledge_item | 当前知识点 + 来源资料片段 | | folder | 分类下资料 + 知识点 | | global | 不检索知识库 | --- ## 顶层 API ```text POST /api/chat/sessions/open-or-create ← 打开或创建 exact scope 会话 POST /api/chat/sessions ← 强制新建当前 scope 会话 GET /api/chat/sessions ← 按 scope 过滤会话列表 GET /api/chat/sessions/:id ← 会话详情 DELETE /api/chat/sessions/:id ← 软删除 PATCH /api/chat/sessions/:id ← 仅 title/pinned/archived ``` `open-or-create` 请求体: ```json { "scopeType": "knowledge_item", "scopeId": "ki_123", "parentKnowledgeBaseId": "kb_001", "parentMaterialId": "mat_001", "createdFrom": "knowledge_item_detail" } ``` 响应: ```json { "sessionId": "chat_001", "isNew": false, "session": { ... } } ``` --- ## 子里程碑 | 编号 | 内容 | |------|------| | M-CHAT-0 | 设计冻结与接口协议(#82 #83) | | M-CHAT-1 | 后端数据模型与迁移(#79 #92 #93 #72 #73 #94) | | M-CHAT-2 | 后端会话打开/创建逻辑(#81 #76 #85 #75 #84) | | M-CHAT-3 | 后端消息发送与检索范围(#74 #86 #87 #88) | | M-CHAT-4 | iOS 入口改造(#39-#44 ios-projects) | | M-CHAT-5 | iOS AI 对话页 Scope 展示(#45-#50 ios-projects) | | M-CHAT-6 | 会话列表与管理(#51-#54 ios-projects #95 #96) | | M-CHAT-7 | 回归测试与旧数据兼容(#78 #89 #90 #91) | --- ## 最小验收链路 ```text 1. 从知识库详情进入 AI → 打开 knowledge_base 会话 ✅ 2. 从资料详情进入 AI → 打开 material 会话 ✅ 3. 从知识点详情进入 AI → 打开 knowledge_item 会话 ✅ 4. 在知识点会话切换到整个知识库 → 打开 knowledge_base 会话 ✅ 5. 在知识库 A 切换到知识库 B → 打开 B 的会话,不复用 A ✅ 6. 在当前 scope 下点新对话 → 创建同 scope 的新 session ✅ ``` 这 6 条跑通,ChatScope 系统才算真正收口。
wangdl added this to the M7:ChatScope 会话系统 — 学习对象绑定的上下文会话 milestone 2026-06-06 16:29:05 +08:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: wangdl/api-server#97
No description provided.