Add project documentation and specs
This commit is contained in:
83
docs/superpowers/specs/2026-03-20-agent-dashboard-design.md
Normal file
83
docs/superpowers/specs/2026-03-20-agent-dashboard-design.md
Normal file
@@ -0,0 +1,83 @@
|
||||
# Agent Dashboard 页面设计规格
|
||||
|
||||
## 概述
|
||||
|
||||
为 Jarvis 系统设计一个 Agent 管理页面,以全息战术投影(Holographic Tactical HUD)风格可视化展示 Master + 4 Sub-Agent 的组织架构,支持查看状态和配置。
|
||||
|
||||
## 视觉风格
|
||||
|
||||
- **主题**:全息战术投影(科幻指挥台)
|
||||
- **背景**:#03050a 深空黑 + 微弱网格线 + 全息扫描线纹理
|
||||
- **节点样式**:半透明玻璃态卡片,悬浮空中,全息光晕边框
|
||||
- **字体**:Orbitron(标题)+ JetBrains Mono(正文)
|
||||
- **配色**:Cyan #00f5d4 主色,Amber #f9a825 强调色,Red #ff4757 危险色
|
||||
|
||||
## 布局结构
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────┐
|
||||
│ AGENT COMMAND CENTER [刷新] [新增] │
|
||||
├──────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌─────────────────────┐ │
|
||||
│ │ MASTER CORE │ │
|
||||
│ │ JARVIS 指挥官 │ │
|
||||
│ │ [●] 状态灯 │ │
|
||||
│ └─────────┬──────────┘ │
|
||||
│ │ │
|
||||
│ ┌───────────────┼───────────────┐ │
|
||||
│ ▼ ▼ ▼ │
|
||||
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
|
||||
│ │ PLANNER │ │ EXECUTOR │ │LIBRARIAN │ │
|
||||
│ │ [●] │ │ [●] │ │ [●] │ │
|
||||
│ │ 规划者 │ │ 执行者 │ │ 知识官 │ │
|
||||
│ │ 调用:12 │ │ 调用:8 │ │ 调用:5 │ │
|
||||
│ └───────────┘ └───────────┘ └───────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌───────────┐ │
|
||||
│ │ ANALYST │ │
|
||||
│ │ [●] │ │
|
||||
│ │ 分析师 │ │
|
||||
│ │ 调用:3 │ │
|
||||
│ └───────────┘ │
|
||||
│ │
|
||||
└──────────────────────────────────────────────────────────┘
|
||||
|
||||
点击节点 → 右侧滑出配置抽屉
|
||||
```
|
||||
|
||||
## 节点卡片字段
|
||||
|
||||
- 名称(Orbitron)
|
||||
- 角色标签(中文)
|
||||
- 状态灯:绿色脉冲=活跃,灰色=空闲
|
||||
- 角色描述(2行)
|
||||
- 调用次数(今日)
|
||||
- 当前任务摘要
|
||||
|
||||
## 连接线
|
||||
|
||||
- 虚线连接 Master → Sub-Agent
|
||||
- 任务触发时:琥珀色脉冲光点沿路径流向目标节点
|
||||
|
||||
## 配置面板(右侧抽屉 400px)
|
||||
|
||||
- Agent 名称
|
||||
- 角色描述
|
||||
- 系统提示词(textarea)
|
||||
- 启用/停用开关
|
||||
- 保存 / 重置按钮
|
||||
|
||||
## 数据来源
|
||||
|
||||
- 固定结构:前端 `src/data/agents.ts`
|
||||
- 运行时状态:`/api/agents/stats`
|
||||
|
||||
## API 设计
|
||||
|
||||
```
|
||||
GET /api/agents/stats → { agent_id, call_count, current_task, status }
|
||||
GET /api/agents/config/{id} → 返回单个 Agent 完整配置
|
||||
PUT /api/agents/config/{id} → 更新 name/description/system_prompt/enabled
|
||||
```
|
||||
192
docs/superpowers/specs/2026-03-20-chat-enhancement-design.md
Normal file
192
docs/superpowers/specs/2026-03-20-chat-enhancement-design.md
Normal file
@@ -0,0 +1,192 @@
|
||||
# 沟通系统增强设计
|
||||
|
||||
## 1. 概述与目标
|
||||
|
||||
在沟通系统(ChatView)中增加两个功能:
|
||||
1. **文件上传** - 用户可在对话中上传文件,AI 自动理解内容并回复
|
||||
2. **表情包选择器** - 在发送按钮旁添加 emoji 选择面板
|
||||
|
||||
## 2. 技术方案
|
||||
|
||||
### 2.1 文件上传
|
||||
|
||||
**前端实现:**
|
||||
- 在 `ChatView.vue` 输入区域添加附件按钮(Paperclip 图标)
|
||||
- 使用 `<input type="file">` 触发文件选择
|
||||
- 支持类型:图片(jpg/png/gif/webp)、文档(pdf/doc/docx/xls/xlsx/ppt/pptx/txt)
|
||||
- 文件大小限制:10MB
|
||||
- 上传时显示进度状态
|
||||
|
||||
**消息气泡展示:**
|
||||
- 文件上传成功后,在对话中显示文件消息气泡
|
||||
- 气泡内容:文件图标 + 文件名 + 文件大小
|
||||
- 点击可下载/预览
|
||||
|
||||
**后端实现:**
|
||||
- 复用现有 `/api/documents/upload` 接口上传文件
|
||||
- 创建 KGNode(entity_type: 'document')关联到对话
|
||||
- 修改 `AgentService.chat_simple()` 支持文件上下文
|
||||
- AI 自动读取上传文件内容并理解
|
||||
|
||||
**数据流:**
|
||||
```
|
||||
用户选择文件 → 前端上传到 /api/documents/upload
|
||||
→ 后端存储文件,创建 KGNode
|
||||
→ 前端发送消息带 file_ids
|
||||
→ AgentService 读取文件内容
|
||||
→ AI 基于文件内容回复
|
||||
```
|
||||
|
||||
### 2.2 表情包选择器
|
||||
|
||||
**前端实现:**
|
||||
- 在发送按钮旁添加 Emoji 图标按钮
|
||||
- 点击展开浮层面板,显示 emoji 分类网格
|
||||
- 分类:😀 笑脸 | 👍 手势 | 📦 物品 | 💬 符号
|
||||
- 每个分类显示常用 emoji 网格
|
||||
- 点击 emoji 插入到输入框
|
||||
- 点击外部关闭面板
|
||||
|
||||
**Emoji 数据:**
|
||||
```typescript
|
||||
const emojiCategories = {
|
||||
smile: ['😀', '😃', '😄', '😁', '😅', '😂', '🤣', '😊', '😇', '🙂', '😉', '😌'],
|
||||
gesture: ['👍', '👎', '👌', '🤌', '🤏', '✌️', '🤞', '🖖', '🤙', '💪', '🙏', '👏'],
|
||||
object: ['📄', '📁', '🖼️', '📊', '📝', '💾', '📧', '🔗', '📌', '🔍', '💡', '⚡'],
|
||||
symbol: ['✅', '❌', '⚠️', '🔥', '💯', '🎯', '⭐', '✨', '💬', '🗨️', '❤️', '🧡']
|
||||
}
|
||||
```
|
||||
|
||||
## 3. API 变更
|
||||
|
||||
### 3.1 修改 ChatRequest
|
||||
|
||||
```python
|
||||
class ChatRequest(BaseModel):
|
||||
message: str
|
||||
conversation_id: str | None = None
|
||||
agent_id: str | None = None
|
||||
file_ids: list[str] = [] # 新增:上传的文件ID列表
|
||||
```
|
||||
|
||||
### 3.2 修改 Message 模型(可选扩展)
|
||||
|
||||
```python
|
||||
class Message(BaseModel):
|
||||
# 新增字段
|
||||
attachments: list[dict] = [] # [{file_id, filename, file_type, file_size}]
|
||||
```
|
||||
|
||||
### 3.3 新增文件读取接口
|
||||
|
||||
```
|
||||
GET /api/documents/{document_id}/content
|
||||
返回: 文件的文本内容(用于 AI 理解)
|
||||
```
|
||||
|
||||
## 4. 组件变更
|
||||
|
||||
### 4.1 ChatView.vue 变更
|
||||
|
||||
**新增:**
|
||||
- `fileInput` ref - 文件 input
|
||||
- `showEmojiPicker` ref - emoji 面板显示状态
|
||||
- `selectedFiles` ref - 已选择待上传文件
|
||||
- `uploadFile()` - 上传文件方法
|
||||
- `insertEmoji()` - 插入 emoji 到输入框
|
||||
|
||||
**修改:**
|
||||
- 输入区域布局:附件按钮 | 输入框 | Emoji按钮 | 发送按钮
|
||||
- `sendMessage()` - 发送前先上传文件,获取 file_ids
|
||||
|
||||
### 4.2 EmojiPicker 组件(新建)
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
defineProps<{
|
||||
visible: boolean
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
select: [emoji: string]
|
||||
close: []
|
||||
}>()
|
||||
|
||||
const categories = {
|
||||
smile: { name: '😀', emojis: [...] },
|
||||
gesture: { name: '👍', emojis: [...] },
|
||||
object: { name: '📦', emojis: [...] },
|
||||
symbol: { name: '💬', emojis: [...] }
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
### 4.3 FileMessage 组件(新建)
|
||||
|
||||
用于展示文件消息气泡:
|
||||
- 文件图标(根据类型)
|
||||
- 文件名(可截断)
|
||||
- 文件大小
|
||||
- 下载按钮
|
||||
|
||||
## 5. 错误处理
|
||||
|
||||
| 场景 | 处理 |
|
||||
|------|------|
|
||||
| 文件类型不支持 | 提示"不支持该文件类型" |
|
||||
| 文件超过10MB | 提示"文件超过10MB限制" |
|
||||
| 上传失败 | 提示"上传失败,请重试",显示重试按钮 |
|
||||
| AI读取文件失败 | AI 回复"无法读取文件内容" |
|
||||
| 网络断开 | 提示"网络连接断开" |
|
||||
|
||||
## 6. 状态定义
|
||||
|
||||
| 状态 | 显示 |
|
||||
|------|------|
|
||||
| 上传中 | 进度环 + 文件名 |
|
||||
| 上传成功 | 文件气泡 |
|
||||
| 上传失败 | 错误图标 + 重试按钮 |
|
||||
| AI 读取中 | AI 思考状态..." |
|
||||
|
||||
## 7. 实现顺序
|
||||
|
||||
1. **Phase 1: 基础 UI**
|
||||
- 添加附件按钮和 Emoji 按钮到输入区域
|
||||
- Emoji 选择器组件
|
||||
- 文件消息气泡组件
|
||||
|
||||
2. **Phase 2: 文件上传**
|
||||
- 前端文件上传逻辑
|
||||
- 消息带 file_ids
|
||||
- 文件气泡展示
|
||||
|
||||
3. **Phase 3: AI 理解文件**
|
||||
- 后端文件内容读取接口
|
||||
- AgentService 支持文件上下文
|
||||
- 测试完整流程
|
||||
|
||||
## 8. 文件结构
|
||||
|
||||
```
|
||||
frontend/src/
|
||||
├── views/
|
||||
│ └── ChatView.vue # 修改 - 添加附件/Emoji按钮
|
||||
├── components/
|
||||
│ ├── chat/
|
||||
│ │ ├── EmojiPicker.vue # 新建 - Emoji 选择器
|
||||
│ │ └── FileMessage.vue # 新建 - 文件消息气泡
|
||||
│ └── stats/ # 已存在
|
||||
│ └── ...
|
||||
└── api/
|
||||
├── conversation.ts # 修改 - chat 支持 file_ids
|
||||
└── document.ts # 新增 - getDocumentContent
|
||||
|
||||
backend/app/
|
||||
├── routers/
|
||||
│ ├── conversation.py # 修改 - ChatRequest 支持 file_ids
|
||||
│ └── document.py # 修改 - 新增 content 接口
|
||||
├── services/
|
||||
│ └── agent_service.py # 修改 - chat 支持文件上下文
|
||||
└── models/
|
||||
└── conversation.py # 修改 - Message 新增 attachments
|
||||
```
|
||||
178
docs/superpowers/specs/2026-03-20-daily-todo-design.md
Normal file
178
docs/superpowers/specs/2026-03-20-daily-todo-design.md
Normal file
@@ -0,0 +1,178 @@
|
||||
# Daily Todo 功能设计文档
|
||||
|
||||
## 概述
|
||||
|
||||
每日待办(Daily Todo)是一个以"天"为维度的任务管理模块,与现有的看板(以项目/多天为维度)形成互补。
|
||||
|
||||
**核心价值:** AI 每天早上自动预生成今日待办(基于前一天未完成的看板任务 + 前一天对话记录),用户可手动增删改。
|
||||
|
||||
## 时区说明
|
||||
|
||||
- 所有日期相关字段均使用**用户本地日期**(后端统一用 `datetime.date.today()` 计算,不依赖 UTC)
|
||||
- `todo_date` 格式:`YYYY-MM-DD`(本地日期字符串),便于按天查询
|
||||
|
||||
## 数据模型
|
||||
|
||||
### DailyTodo 表
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | String(36) | 主键,UUID |
|
||||
| user_id | String(36) | 所属用户,索引 |
|
||||
| title | String(500) | 待办标题 |
|
||||
| is_completed | Boolean | 是否完成,默认 false |
|
||||
| source | Enum | `ai_kanban` / `ai_chat` / `manual`,来源 |
|
||||
| source_detail | String(500) | 展示用说明文本,如"看板:完成用户登录功能" |
|
||||
| source_ref_id | String(36) | 来源原始ID(看板TaskID或对话ConversationID),可空 |
|
||||
| todo_date | String(10) | 所属日期,格式 YYYY-MM-DD,复合索引 (user_id, todo_date) |
|
||||
| completed_at | DateTime | 完成时间,可空 |
|
||||
| created_at | DateTime | 创建时间 |
|
||||
| updated_at | DateTime | 更新时间 |
|
||||
|
||||
**索引:** `INDEX (user_id, todo_date)`,查询今日待办的主要路径
|
||||
|
||||
### DailyTodoHistory 归档表
|
||||
|
||||
归档时机:每天凌晨 1:00,APScheduler 清理 7 天前的记录
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | String(36) | 主键,UUID |
|
||||
| original_id | String(36) | 原记录ID(原记录归档后可能已删除) |
|
||||
| user_id | String(36) | 所属用户 |
|
||||
| title | String(500) | 待办标题 |
|
||||
| is_completed | Boolean | 最终完成状态 |
|
||||
| source | Enum | 来源 |
|
||||
| source_detail | String(500) | 展示用说明文本 |
|
||||
| todo_date | String(10) | 所属日期 |
|
||||
| completed_at | DateTime | 完成时间 |
|
||||
| created_at | DateTime | 创建时间 |
|
||||
| archived_at | DateTime | 归档时间 |
|
||||
|
||||
**保留策略:** 归档记录保留 7 天,到期自动删除(APScheduler 每日清理)
|
||||
|
||||
## 核心功能
|
||||
|
||||
### F1: 今日待办列表
|
||||
- 展示当天的所有待办事项
|
||||
- 每条可勾选完成状态(勾选后划线 + 变灰)
|
||||
- 支持新增、编辑、删除
|
||||
- 按创建时间倒序排列
|
||||
- 分页:每页 50 条,支持 `page` + `page_size` 参数
|
||||
|
||||
### F2: 历史记录
|
||||
- 可查看昨天、前天等历史日期的待办
|
||||
- 切换日期查看,**只读**(历史不允许修改/删除)
|
||||
- 历史数据来自 `DailyTodo` 表(按 todo_date 过滤)
|
||||
- 注:不从 `DailyTodoHistory` 表读取——归档表仅作备份保留
|
||||
|
||||
### F3: AI 自动预生成
|
||||
- 触发时机:每天早上 8:00(APScheduler 定时任务),也可手动触发
|
||||
- 数据来源:
|
||||
1. **看板任务**:前一天创建的、状态 ≠ done 的任务,取前 20 条(按 created_at 倒序)
|
||||
2. **对话记录**:前一天创建的对话,取其消息内容前 2000 字发给 LLM
|
||||
- AI 处理流程:
|
||||
1. 查询上述数据,拼装为分析文本
|
||||
2. 发送给 LLM,Prompt 要求输出 JSON 数组:`[{ "title": "...", "reason": "..." }]`
|
||||
3. 解析 LLM 返回,若返回为空或解析失败则跳过对话分析
|
||||
4. 批量写入 DailyTodo 表(source=ai_kanban / ai_chat)
|
||||
- **幂等处理(关键)**:使用事务 + 插入前检查,确保同一天不会重复生成
|
||||
```
|
||||
BEGIN TRANSACTION
|
||||
IF EXISTS (SELECT 1 FROM daily_todos WHERE user_id=? AND todo_date=? AND source IN ('ai_kanban','ai_chat')):
|
||||
ROLLBACK -- 已有AI生成,跳过
|
||||
ELSE:
|
||||
INSERT ... -- 批量写入
|
||||
COMMIT
|
||||
```
|
||||
- **容错**:LLM 不可用时记录日志,跳过该部分,不阻塞整体流程
|
||||
- 看板任务上限 20 条,对话分析最多提取 3 条
|
||||
|
||||
### F4: AI 来源说明
|
||||
- 每条 AI 生成的待办,显示其来源说明
|
||||
- `source=ai_kanban`:`source_detail` = "看板:{任务标题}",`source_ref_id` = 原始 Task ID
|
||||
- `source=ai_chat`:`source_detail` = "对话:{reason 摘要(截取前60字)}"
|
||||
|
||||
## API 设计
|
||||
|
||||
### GET /api/todos
|
||||
查询待办列表(支持分页)
|
||||
- Query: `?date=2026-03-20&page=1&page_size=50`(date 默认当天)
|
||||
- Response:
|
||||
```json
|
||||
{
|
||||
"items": [DailyTodoOut],
|
||||
"total": 12,
|
||||
"page": 1,
|
||||
"page_size": 50
|
||||
}
|
||||
```
|
||||
|
||||
### POST /api/todos
|
||||
新增待办(手动)
|
||||
- Body: `{ title: string }`
|
||||
- source 固定为 `manual`,todo_date 为当天
|
||||
|
||||
### PATCH /api/todos/{id}
|
||||
更新待办(完成状态 / 标题)
|
||||
- Body: `{ is_completed?: boolean, title?: string }`
|
||||
- 仅当日待办可修改,历史日期返回 403
|
||||
|
||||
### DELETE /api/todos/{id}
|
||||
删除待办
|
||||
- 仅当日待办可删除,历史日期返回 403
|
||||
|
||||
### POST /api/todos/ai-generate
|
||||
手动触发 AI 预生成
|
||||
- 检查今日是否已有 AI 生成记录,有则返回 200(幂等,不重复生成)
|
||||
- 无则执行 AI 分析流程,返回生成结果
|
||||
|
||||
### GET /api/todos/summary
|
||||
获取今日待办摘要
|
||||
- Response: `{ date: "2026-03-20", total: 5, completed: 2, pending: 3 }`
|
||||
|
||||
## 响应 Schema
|
||||
|
||||
### DailyTodoOut
|
||||
```json
|
||||
{
|
||||
"id": "uuid",
|
||||
"title": "完成用户登录功能",
|
||||
"is_completed": false,
|
||||
"source": "ai_kanban",
|
||||
"source_detail": "看板:完成用户登录功能",
|
||||
"todo_date": "2026-03-20",
|
||||
"completed_at": null,
|
||||
"created_at": "2026-03-20T08:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
## 定时任务
|
||||
|
||||
| 任务 | 时间 | 说明 |
|
||||
|------|------|------|
|
||||
| AI预生成 | 每天 08:00 | 为所有活跃用户执行 AI 预生成 |
|
||||
| 历史归档清理 | 每天 01:00 | 删除 7 天前已归档的 DailyTodo 记录 |
|
||||
|
||||
## 前端页面
|
||||
|
||||
### TodoView.vue
|
||||
- 路径:`/todo`
|
||||
- 布局:顶部日期导航 + 下方待办列表
|
||||
- 日期导航:今天、昨天、前天快捷按钮 + 日期选择器
|
||||
- 今日视图:输入框新增 + 列表 + "AI 规划今日"按钮
|
||||
- 历史视图:只读列表,无新增/删除按钮,灰色禁用样式
|
||||
- 交互细节:
|
||||
- 勾选完成:Motion 动画划线效果
|
||||
- 加载状态:骨架屏
|
||||
- 空状态:终端风格空提示
|
||||
- 风格:sci-fi 全息终端,cyan (#00f5d4) + #03050a,与 AgentView 一致
|
||||
|
||||
### 侧边栏
|
||||
- 新增菜单项:`{ name: '待办', path: '/todo', icon: CheckSquare }`
|
||||
|
||||
## 技术依赖
|
||||
|
||||
- 后端:FastAPI + SQLAlchemy + APScheduler + LLM Service
|
||||
- 前端:Vue 3 Composition API + 复用 api/index 的 axios 实例
|
||||
- 数据库:新表 DailyTodo + DailyTodoHistory(迁移 Alembic 或手动 CREATE TABLE)
|
||||
@@ -0,0 +1,602 @@
|
||||
# Jarvis 个人 AI 助理 — 设计规格书
|
||||
|
||||
> 版本:v1.0
|
||||
> 日期:2026-03-20
|
||||
> 作者:Jarvis 设计团队
|
||||
|
||||
---
|
||||
|
||||
## 1. 项目概述
|
||||
|
||||
### 1.1 项目目标
|
||||
|
||||
构建一个拟人化的个人 AI 助理系统,代号 **Jarvis**。核心目标是打造一个真正"懂你"的智能体 —— 理解你的知识体系、工作安排和个人偏好,而不仅仅是关键词匹配回答问题。
|
||||
|
||||
### 1.2 核心价值
|
||||
|
||||
- **知识回溯能力** — 基于 LlamaIndex Node 关系 + 知识图谱双层架构,确保 AI 真正理解你的知识和工作的内在联系
|
||||
- **拟人化协作** — 多 Agent 角色协同,每个角色有独立职责,像真实团队成员一样交流
|
||||
- **全端覆盖** — Web + Android 双端,随时随地与 Jarvis 对话
|
||||
- **本地部署** — 所有数据存储在 NAS,数据完全自主可控
|
||||
|
||||
---
|
||||
|
||||
## 2. 技术栈
|
||||
|
||||
| 层级 | 技术选型 | 说明 |
|
||||
|------|---------|------|
|
||||
| **Web 前端** | Vue 3 + TypeScript | Composition API,响应式 UI |
|
||||
| **移动端** | Kotlin (Android) | Jetpack Compose,轻量连接器 |
|
||||
| **后端框架** | FastAPI (Python 3.12+) | 高性能 ASGI,支持 async |
|
||||
| **Agent 框架** | LangGraph | 多 Agent 编排、工具调用、状态机流转 |
|
||||
| **LLM 适配器** | LangChain Claude / OpenAI / Ollama | 可切换,不影响上层逻辑 |
|
||||
| **知识库框架** | LlamaIndex | Node 关系索引、语义检索 |
|
||||
| **向量数据库** | ChromaDB | 轻量级向量存储 |
|
||||
| **关系数据库** | SQLite | 轻量数据持久化 |
|
||||
| **定时任务** | APScheduler | 定时任务调度 |
|
||||
| **部署环境** | NAS (本地) | Docker 容器化部署 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 系统架构
|
||||
|
||||
### 3.1 整体架构图
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
│ 用户端 │
|
||||
│ ┌──────────────────┐ ┌──────────────────┐ │
|
||||
│ │ Web 前端 │ │ Android App │ │
|
||||
│ │ (Vue 3 + TS) │ │ (Kotlin) │ │
|
||||
│ └────────┬─────────┘ └────────┬─────────┘ │
|
||||
└───────────┼────────────────────────┼─────────────────┘
|
||||
│ │
|
||||
│ HTTP / WebSocket │
|
||||
└────────┬────────────────┘
|
||||
│
|
||||
┌────────────────────▼─────────────────────────────────┐
|
||||
│ FastAPI 后端服务 │
|
||||
│ (NAS Docker 容器) │
|
||||
│ │
|
||||
│ ┌───────────────────────────────────────────────┐ │
|
||||
│ │ 多 Agent 调度系统 │ │
|
||||
│ │ ┌─────────┐ │ │
|
||||
│ │ │ 主Agent │ ◄── 协调者,统一入口 │ │
|
||||
│ │ │(调度员) │ │ │
|
||||
│ │ └────┬────┘ │ │
|
||||
│ │ ├──► 规划Agent ──► 任务拆解、计划制定 │ │
|
||||
│ │ ├──► 执行Agent ──► 工具调用、任务执行 │ │
|
||||
│ │ ├──► 知识管理员 ──► 知识库管理、图谱更新 │ │
|
||||
│ │ └──► 分析师Agent ──► 数据分析、报告生成 │ │
|
||||
│ │ └──► [可扩展] ────► 新角色注册机制 │ │
|
||||
│ └───────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌──────────────┐ │
|
||||
│ │ LLM 适配器 │ │ 定时任务 │ │ 论坛扫描 │ │
|
||||
│ │ LangChain │ │ 引擎 │ │ 引擎 │ │
|
||||
│ │ (可切换) │ │ │ │ │ │
|
||||
│ └─────────────┘ └─────────────┘ └──────────────┘ │
|
||||
└──────────────────────────┬────────────────────────────┘
|
||||
│
|
||||
┌─────────────────────┼─────────────────────┐
|
||||
│ │ │
|
||||
┌────▼────┐ ┌─────────────▼────┐ ┌──────────▼────────┐
|
||||
│ ChromaDB│ │ SQLite │ │ 文件存储 │
|
||||
│向量数据库│ │ (关系数据) │ │ (NAS 共享目录) │
|
||||
└─────────┘ └───────────────────┘ └────────────────────┘
|
||||
```
|
||||
|
||||
### 3.2 通信模式
|
||||
|
||||
- **协作式 + 主 Agent 协调**
|
||||
- 主 Agent 作为统一入口,接收用户请求后分发到子 Agent
|
||||
- 子 Agent 完成任务后汇总结果给主 Agent
|
||||
- 子 Agent 之间可通过主 Agent 传递信息
|
||||
- 支持新增 Agent 注册到系统中
|
||||
|
||||
---
|
||||
|
||||
## 4. 核心功能模块
|
||||
|
||||
### 4.1 多 Agent 调度系统
|
||||
|
||||
#### Agent 角色定义
|
||||
|
||||
| Agent | 职责 | 核心能力 |
|
||||
|-------|------|---------|
|
||||
| **主Agent (Jarvis)** | 协调调度、对话入口 | 意图识别、任务分发、结果汇总 |
|
||||
| **规划Agent** | 制定每日计划 | 任务拆解、优先级排序、时间规划 |
|
||||
| **执行Agent** | 执行具体任务 | 工具调用、进度追踪、结果反馈 |
|
||||
| **知识管理员** | 管理知识库和图谱 | 文档索引、实体提取、图谱更新 |
|
||||
| **分析师Agent** | 分析工作数据 | 数据统计、趋势分析、报告生成 |
|
||||
|
||||
#### Agent 扩展机制
|
||||
|
||||
- 通过配置文件或 API 注册新 Agent
|
||||
- 每个 Agent 有独立的 system prompt 和工具集
|
||||
- 新增 Agent 自动出现在对话上下文中
|
||||
|
||||
### 4.2 知识库系统
|
||||
|
||||
#### 文档处理流程
|
||||
|
||||
```
|
||||
用户上传文件
|
||||
│
|
||||
▼
|
||||
文件解析
|
||||
├── Markdown → 直接读取
|
||||
├── PDF → PDF 解析(PyMuPDF)
|
||||
├── DOCX → python-docx
|
||||
└── TXT → 直接读取
|
||||
│
|
||||
▼
|
||||
LlamaIndex Node 构建
|
||||
├── 按标题层级切分(Header-based Chunking)
|
||||
├── 保留 Node 关系链表(PARENT, PREVIOUS, NEXT, SOURCE)
|
||||
└── 每个 Node 包含 metadata(标题、章节、页码)
|
||||
│
|
||||
▼
|
||||
向量存储 → ChromaDB
|
||||
│
|
||||
▼
|
||||
知识图谱构建
|
||||
├── LLM 实体识别(从 Node 内容中提取)
|
||||
├── LLM 关系抽取(实体之间的关系)
|
||||
└── 存入 SQLite(nodes + edges 表)
|
||||
```
|
||||
|
||||
#### 检索流程(Small-to-Big 策略)
|
||||
|
||||
```
|
||||
用户提问
|
||||
│
|
||||
▼
|
||||
ChromaDB 向量检索
|
||||
├── 用小 Chunk 精确匹配
|
||||
└── 返回多个相关 Node
|
||||
│
|
||||
▼
|
||||
上下文回溯
|
||||
├── 顺着 Node 关系找到完整章节(父 Node)
|
||||
└── 附加上下文给 LLM
|
||||
│
|
||||
▼
|
||||
LLM 生成回答
|
||||
```
|
||||
|
||||
### 4.3 知识图谱系统
|
||||
|
||||
#### 图谱数据结构
|
||||
|
||||
```sql
|
||||
-- 知识图谱节点表
|
||||
knowledge_graph_nodes (
|
||||
id TEXT PRIMARY KEY,
|
||||
user_id TEXT, -- 用户隔离(支持多用户)
|
||||
entity_type TEXT, -- 实体类型:PERSON / EVENT / CONCEPT / OBJECT
|
||||
entity_name TEXT, -- 实体名称
|
||||
description TEXT, -- 实体描述
|
||||
source_doc_id TEXT, -- 来源文档
|
||||
source_node_id TEXT, -- 来源 Node
|
||||
importance REAL, -- 重要程度 (0-1)
|
||||
created_at TIMESTAMP,
|
||||
updated_at TIMESTAMP
|
||||
)
|
||||
|
||||
-- 知识图谱边表
|
||||
knowledge_graph_edges (
|
||||
id TEXT PRIMARY KEY,
|
||||
user_id TEXT, -- 用户隔离
|
||||
source_node_id TEXT,
|
||||
target_node_id TEXT,
|
||||
relation_type TEXT, -- 关系类型:包含 / 依赖 / 相关 / 导致 / 属于
|
||||
weight REAL, -- 关系权重 (0-1)
|
||||
created_at TIMESTAMP,
|
||||
FOREIGN KEY (source_node_id) REFERENCES knowledge_graph_nodes(id),
|
||||
FOREIGN KEY (target_node_id) REFERENCES knowledge_graph_nodes(id)
|
||||
)
|
||||
```
|
||||
|
||||
#### 图谱更新机制
|
||||
|
||||
- **事件驱动**:文档上传/任务变更时实时触发
|
||||
- **定时同步**:每日凌晨增量扫描,防止遗漏
|
||||
- **手动触发**:用户可主动要求重建图谱
|
||||
- **增量检测**:基于文件 mtime + 内容 hash 判断文档是否变化
|
||||
|
||||
#### 数据模型
|
||||
|
||||
```sql
|
||||
-- 文档表
|
||||
documents (
|
||||
id TEXT PRIMARY KEY,
|
||||
user_id TEXT, -- 用户隔离
|
||||
filename TEXT,
|
||||
file_type TEXT, -- pdf / markdown / docx / txt
|
||||
file_path TEXT, -- NAS 存储路径
|
||||
file_hash TEXT, -- 内容 hash,用于增量检测
|
||||
summary TEXT, -- AI 生成的文档摘要
|
||||
file_size INTEGER,
|
||||
created_at TIMESTAMP,
|
||||
updated_at TIMESTAMP
|
||||
)
|
||||
|
||||
-- 文档分块表(LlamaIndex Node 映射)
|
||||
document_chunks (
|
||||
id TEXT PRIMARY KEY,
|
||||
user_id TEXT, -- 用户隔离
|
||||
document_id TEXT,
|
||||
chunk_index INTEGER, -- 在文档中的顺序
|
||||
content TEXT, -- 原始文本内容
|
||||
metadata JSON, -- LlamaIndex Node metadata(包含 title、chapter、relationships 等)
|
||||
embedding_id TEXT, -- ChromaDB 中的向量 ID
|
||||
created_at TIMESTAMP,
|
||||
FOREIGN KEY (document_id) REFERENCES documents(id)
|
||||
)
|
||||
```
|
||||
|
||||
#### 图谱可视化
|
||||
|
||||
- 前端 Web 端展示交互式知识图谱
|
||||
- 节点可点击查看详情
|
||||
- 支持按类型筛选、按时间筛选
|
||||
- 支持搜索实体名称
|
||||
|
||||
### 4.4 论坛系统
|
||||
|
||||
#### 功能设计
|
||||
|
||||
- **发布内容** — 你在论坛发布想法、指令、问题
|
||||
- **AI 扫描** — Jarvis 定时扫描论坛内容
|
||||
- **任务识别** — 识别可执行的任务转为看板任务
|
||||
- **互动回应** — AI 在帖子下回复,像团队成员讨论
|
||||
|
||||
#### 数据模型
|
||||
|
||||
```sql
|
||||
forum_posts (
|
||||
id TEXT PRIMARY KEY,
|
||||
user_id TEXT, -- 发帖用户
|
||||
title TEXT,
|
||||
content TEXT,
|
||||
parent_id TEXT, -- 回复的帖子 ID(自关联,支持嵌套回复)
|
||||
status TEXT, -- pending / processing / completed
|
||||
created_at TIMESTAMP,
|
||||
updated_at TIMESTAMP
|
||||
)
|
||||
```
|
||||
|
||||
### 4.5 看板系统
|
||||
|
||||
#### 功能设计
|
||||
|
||||
- **任务管理** — 创建、编辑、删除任务
|
||||
- **状态流转** — 待办 / 进行中 / 已完成 / 已取消
|
||||
- **优先级** — P0 / P1 / P2 / P3
|
||||
- **AI 凌晨分析** — 每日凌晨分析完成情况,规划次日任务
|
||||
- **AI 建议** — 根据你的工作模式给出优先级建议
|
||||
|
||||
#### 数据模型
|
||||
|
||||
```sql
|
||||
tasks (
|
||||
id TEXT PRIMARY KEY,
|
||||
user_id TEXT, -- 用户隔离
|
||||
title TEXT,
|
||||
description TEXT,
|
||||
priority TEXT, -- P0 / P1 / P2 / P3
|
||||
status TEXT, -- todo / in_progress / done / cancelled
|
||||
deadline TIMESTAMP,
|
||||
created_at TIMESTAMP,
|
||||
updated_at TIMESTAMP,
|
||||
completed_at TIMESTAMP
|
||||
)
|
||||
|
||||
task_history (
|
||||
id TEXT PRIMARY KEY,
|
||||
task_id TEXT,
|
||||
action TEXT, -- created / updated / completed / cancelled
|
||||
old_value TEXT,
|
||||
new_value TEXT,
|
||||
timestamp TIMESTAMP,
|
||||
FOREIGN KEY (task_id) REFERENCES tasks(id)
|
||||
)
|
||||
```
|
||||
|
||||
### 4.6 Markdown 编辑器
|
||||
|
||||
#### 功能设计
|
||||
|
||||
- 浏览器端在线编辑 Markdown
|
||||
- 支持实时预览
|
||||
- AI 辅助功能:
|
||||
- AI 续写
|
||||
- AI 润色
|
||||
- AI 总结
|
||||
- 自动保存到知识库
|
||||
- 支持创建新文档和编辑已有文档
|
||||
|
||||
### 4.7 定时任务引擎
|
||||
|
||||
#### 内置定时任务
|
||||
|
||||
| 任务 | 触发时间 | 功能 |
|
||||
|------|---------|------|
|
||||
| 论坛扫描 | 可配置(默认每小时) | 扫描新帖子,识别可执行任务 |
|
||||
| 图谱增量同步 | 每日凌晨 2:00 | 扫描文档变化,更新知识图谱 |
|
||||
| 每日规划 | 每日早上 8:00 | 分析昨日任务完成情况,规划当日 |
|
||||
| 知识摘要 | 每周一凌晨 | 生成上周工作摘要 |
|
||||
|
||||
---
|
||||
|
||||
## 5. 数据库设计
|
||||
|
||||
### 5.1 ER 图
|
||||
|
||||
```
|
||||
users
|
||||
│
|
||||
▼
|
||||
documents ──► document_chunks ──► embeddings (ChromaDB)
|
||||
│
|
||||
▼
|
||||
knowledge_graph_nodes ◄──► knowledge_graph_edges
|
||||
│
|
||||
▼
|
||||
tasks ◄─── task_history
|
||||
│
|
||||
▼
|
||||
forum_posts (自关联: parent_id ──► forum_posts.id)
|
||||
│
|
||||
▼
|
||||
conversations ──► messages
|
||||
```
|
||||
|
||||
### 5.2 核心表结构
|
||||
|
||||
| 表名 | 说明 |
|
||||
|------|------|
|
||||
| `users` | 用户信息 |
|
||||
| `documents` | 上传的文档元数据 |
|
||||
| `document_chunks` | LlamaIndex Node 映射(保留关系) |
|
||||
| `knowledge_graph_nodes` | 知识图谱节点 |
|
||||
| `knowledge_graph_edges` | 知识图谱边 |
|
||||
| `tasks` | 看板任务 |
|
||||
| `task_history` | 任务变更历史 |
|
||||
| `forum_posts` | 论坛帖子(含回复,通过 parent_id 自关联) |
|
||||
| `conversations` | 主对话会话 |
|
||||
| `messages` | 对话消息 |
|
||||
| `knowledge_summaries` | 历史对话摘要 |
|
||||
|
||||
#### 对话数据模型
|
||||
|
||||
```sql
|
||||
conversations (
|
||||
id TEXT PRIMARY KEY,
|
||||
user_id TEXT, -- 用户隔离
|
||||
title TEXT,
|
||||
created_at TIMESTAMP,
|
||||
updated_at TIMESTAMP
|
||||
)
|
||||
|
||||
messages (
|
||||
id TEXT PRIMARY KEY,
|
||||
conversation_id TEXT,
|
||||
role TEXT, -- user / assistant
|
||||
content TEXT,
|
||||
model TEXT, -- 使用的模型
|
||||
created_at TIMESTAMP,
|
||||
FOREIGN KEY (conversation_id) REFERENCES conversations(id)
|
||||
)
|
||||
|
||||
knowledge_summaries (
|
||||
id TEXT PRIMARY KEY,
|
||||
user_id TEXT,
|
||||
period TEXT, -- daily / weekly / monthly
|
||||
period_start DATE,
|
||||
period_end DATE,
|
||||
summary TEXT, -- 摘要内容
|
||||
created_at TIMESTAMP
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. API 设计
|
||||
|
||||
### 6.1 主要 API 端点
|
||||
|
||||
> **通用规则**:所有列表接口支持分页参数 `page`(页码,默认 1)和 `page_size`(每页数量,默认 20)。返回格式统一为 `{ data: [...], total: N, page: X, page_size: Y }`。
|
||||
|
||||
#### 认证接口
|
||||
- `POST /api/auth/register` — 用户注册
|
||||
- `POST /api/auth/login` — 用户登录,返回 JWT Token
|
||||
- `POST /api/auth/refresh` — 刷新 Token
|
||||
- `POST /api/auth/logout` — 登出
|
||||
|
||||
#### 对话接口
|
||||
- `POST /api/chat` — 发送消息,获取 AI 回复
|
||||
- `GET /api/conversations?page=&page_size=` — 获取对话历史列表
|
||||
- `GET /api/conversations/{id}/messages?page=&page_size=` — 获取对话消息
|
||||
|
||||
#### 知识库接口
|
||||
- `POST /api/documents/upload` — 上传文档(支持 multipart/form-data,最大 50MB)
|
||||
- `GET /api/documents?page=&page_size=` — 获取文档列表
|
||||
- `DELETE /api/documents/{id}` — 删除文档
|
||||
- `POST /api/documents/{id}/reindex` — 重建索引(幂等操作)
|
||||
- `POST /api/search` — 语义搜索
|
||||
- 请求体:`{ "query": "搜索内容", "top_k": 5, "filters": {} }`
|
||||
|
||||
#### 知识图谱接口
|
||||
- `GET /api/knowledge-graph` — 获取图谱数据
|
||||
- `POST /api/knowledge-graph/rebuild` — 触发图谱重建(幂等,带锁防止并发)
|
||||
- `GET /api/knowledge-graph/search?q=` — 搜索实体
|
||||
|
||||
#### 看板接口
|
||||
- `GET /api/tasks?page=&page_size=&status=` — 获取任务列表
|
||||
- `POST /api/tasks` — 创建任务
|
||||
- `PUT /api/tasks/{id}` — 更新任务
|
||||
- `DELETE /api/tasks/{id}` — 删除任务
|
||||
|
||||
#### 论坛接口
|
||||
- `GET /api/forum/posts?page=&page_size=` — 获取帖子列表
|
||||
- `POST /api/forum/posts` — 发布帖子
|
||||
- `GET /api/forum/posts/{id}` — 获取帖子详情(含回复树)
|
||||
- `POST /api/forum/posts/{id}/reply` — 回复帖子
|
||||
|
||||
#### Markdown 编辑器接口
|
||||
- `GET /api/notes?page=&page_size=` — 获取笔记列表
|
||||
- `POST /api/notes` — 创建笔记
|
||||
- `PUT /api/notes/{id}` — 更新笔记
|
||||
- `DELETE /api/notes/{id}` — 删除笔记
|
||||
- `POST /api/notes/{id}/ai-assist` — AI 辅助操作
|
||||
- 请求体:`{ "action": "continue" | "polish" | "summarize" }`
|
||||
|
||||
### 6.2 WebSocket 实时通信
|
||||
|
||||
消息格式统一为 JSON:
|
||||
```json
|
||||
// 通用消息结构
|
||||
{
|
||||
"type": "chat_message" | "graph_update" | "task_update",
|
||||
"payload": { ... },
|
||||
"timestamp": "ISO8601"
|
||||
}
|
||||
```
|
||||
|
||||
- `/ws/chat` — 实时对话(流式输出)
|
||||
- `/ws/knowledge-graph` — 图谱更新实时推送
|
||||
- `/ws/tasks` — 任务状态变化实时推送
|
||||
|
||||
---
|
||||
|
||||
## 7. 前端设计
|
||||
|
||||
### 7.1 Web 端页面结构
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ 顶部导航栏 │
|
||||
│ [对话] [知识库] [图谱] [看板] [论坛] [笔记] │
|
||||
└─────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────┐
|
||||
│ │
|
||||
│ 主内容区域 │
|
||||
│ │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 7.2 核心页面
|
||||
|
||||
| 页面 | 功能 |
|
||||
|------|------|
|
||||
| **对话页** | 主对话界面,Jarvis 头像,消息列表,输入框 |
|
||||
| **知识库页** | 文档列表,上传入口,搜索框 |
|
||||
| **图谱页** | 交互式知识图谱,节点详情侧边栏 |
|
||||
| **看板页** | 任务看板(Kanban 布局),AI 规划建议 |
|
||||
| **论坛页** | 帖子列表,发帖入口,AI 回复展示 |
|
||||
| **笔记页** | Markdown 编辑器,笔记列表 |
|
||||
|
||||
### 7.3 Android 端
|
||||
|
||||
- 独立对话窗口,直接与 Jarvis 对话
|
||||
- 任务查看和简单编辑
|
||||
- 推送通知(每日规划提醒、任务到期提醒)
|
||||
- 核心是**对话遥控**,重度操作建议用 Web 端
|
||||
|
||||
---
|
||||
|
||||
## 8. 部署架构
|
||||
|
||||
### 8.1 NAS 部署方案
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────┐
|
||||
│ NAS │
|
||||
│ │
|
||||
│ ┌────────────────────────────────────────────┐ │
|
||||
│ │ Docker Compose │ │
|
||||
│ │ │ │
|
||||
│ │ ┌──────────────┐ ┌──────────────────┐ │ │
|
||||
│ │ │ Jarvis API │ │ ChromaDB │ │ │
|
||||
│ │ │ (FastAPI) │ │ (向量数据) │ │ │
|
||||
│ │ └──────────────┘ └──────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ │ ┌──────────────┐ ┌──────────────────┐ │ │
|
||||
│ │ │ SQLite │ │ 文件存储 │ │ │
|
||||
│ │ │ (关系数据) │ │ /data/files │ │ │
|
||||
│ │ └──────────────┘ └──────────────────┘ │ │
|
||||
│ └────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ NAS 共享目录 /data 挂载到容器 │
|
||||
└──────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 8.2 环境变量配置
|
||||
|
||||
```env
|
||||
# LLM 配置
|
||||
LLM_PROVIDER=claude # claude / deepseek / ollama
|
||||
CLAUDE_API_KEY=xxx
|
||||
DEEPSEEK_API_KEY=xxx
|
||||
OLLAMA_BASE_URL=http://localhost:11434
|
||||
OLLAMA_MODEL=llama3
|
||||
|
||||
# 数据库配置
|
||||
DATABASE_URL=sqlite+aiosqlite:///data/jarvis.db
|
||||
CHROMA_PERSIST_DIR=/data/chroma
|
||||
|
||||
# 文件存储
|
||||
FILE_STORAGE_DIR=/data/files
|
||||
|
||||
# 定时任务配置
|
||||
FORUM_SCAN_INTERVAL=3600 # 秒
|
||||
DAILY_PLAN_TIME=08:00
|
||||
GRAPH_SYNC_TIME=02:00
|
||||
|
||||
# JWT 认证
|
||||
JWT_SECRET=xxx
|
||||
JWT_ALGORITHM=HS256
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. 安全设计
|
||||
|
||||
- **JWT 认证** — 所有 API 需要 Token 验证
|
||||
- **数据加密** — SQLite 数据库可配置加密
|
||||
- **文件隔离** — 用户上传文件存储在独立目录
|
||||
- **API 限流** — 防止 API 滥用
|
||||
- **敏感信息** — API Key 等存储在环境变量,不进入代码库
|
||||
|
||||
---
|
||||
|
||||
## 10. 未来扩展方向
|
||||
|
||||
- **多模态支持** — 图片、音频、视频解析
|
||||
- **更多 Agent** — 按领域细分的专业助手
|
||||
- **插件系统** — 第三方工具集成
|
||||
- **团队协作** — 多用户知识共享
|
||||
- **云端同步** — 异地数据备份
|
||||
|
||||
---
|
||||
|
||||
## 11. 开发阶段建议
|
||||
|
||||
> **注意**:Phase 3 的知识图谱依赖 Phase 1 的知识库基础设施。Phase 1-3 为核心 MVP,需按顺序开发。
|
||||
|
||||
| 阶段 | 内容 | 优先级 |
|
||||
|------|------|--------|
|
||||
| **Phase 1** | 基础框架搭建、对话系统、知识库上传检索 | P0 |
|
||||
| **Phase 2** | 看板系统、论坛系统、Markdown 编辑器 | P0 |
|
||||
| **Phase 3** | 知识图谱构建与可视化、多 Agent 协同 | P0 |
|
||||
| **Phase 4** | 定时任务引擎、AI 每日规划功能 | P1 |
|
||||
| **Phase 5** | Android App 开发 | P1 |
|
||||
| **Phase 6** | 优化与扩展 | P2 |
|
||||
|
||||
---
|
||||
|
||||
*本文档为 Jarvis 个人 AI 助理系统的初始设计规格,将根据开发进展持续更新。*
|
||||
@@ -0,0 +1,141 @@
|
||||
# LangSmith 集成设计文档
|
||||
|
||||
**日期**: 2026-03-20
|
||||
**状态**: 设计中
|
||||
**范围**: 后端 LangGraph Agent 追踪
|
||||
|
||||
---
|
||||
|
||||
## 1. 背景与目标
|
||||
|
||||
Jarvis 后端基于 LangGraph 构建了多智能体系统(Master/Planner/Executor/Librarian/Analyst),目前没有可观测性能力。
|
||||
|
||||
本次集成目标:
|
||||
1. **调用追踪** — 在 LangSmith Dashboard 查看完整的 Agent 执行轨迹
|
||||
2. **对话历史管理** — 按 run_id 聚合对话,自动存储到 LangSmith
|
||||
3. **评估支持** — 积累的对话数据可用于 LangSmith Evaluation
|
||||
|
||||
---
|
||||
|
||||
## 2. 集成方案(方案 A:最小集成)
|
||||
|
||||
### 2.1 核心思路
|
||||
|
||||
LangGraph 内置对 LangSmith 的支持,只需三步即可完成集成:
|
||||
|
||||
1. 在 `.env` 中配置 LangSmith 环境变量
|
||||
2. 在 `pyproject.toml` 中添加 `langsmith` 为直接依赖
|
||||
3. 在 `llm_service.py` 中为 LLM 调用注入 LangSmith Callback
|
||||
|
||||
LangGraph 的 `compile()` 会自动将 Callback 传递到所有节点,无需修改 `graph.py`。
|
||||
|
||||
### 2.2 环境变量
|
||||
|
||||
在 `backend/.env.example` 中新增:
|
||||
|
||||
```env
|
||||
# LangSmith Tracing
|
||||
LANGSMITH_TRACING=true
|
||||
LANGSMITH_API_KEY=your-langsmith-api-key
|
||||
LANGSMITH_PROJECT=jarvis-agent
|
||||
```
|
||||
|
||||
### 2.3 依赖
|
||||
|
||||
在 `backend/pyproject.toml` 的 `dependencies` 中添加:
|
||||
|
||||
```toml
|
||||
"langsmith>=0.1.0",
|
||||
```
|
||||
|
||||
### 2.4 配置类变更
|
||||
|
||||
在 `backend/app/config.py` 中新增配置字段:
|
||||
|
||||
```python
|
||||
# LangSmith
|
||||
LANGSMITH_TRACING: bool = False
|
||||
LANGSMITH_API_KEY: str = ""
|
||||
LANGSMITH_PROJECT: str = "jarvis-agent"
|
||||
```
|
||||
|
||||
### 2.5 实现变更
|
||||
|
||||
#### 2.5.1 Config 层
|
||||
|
||||
在 `backend/app/config.py` 中新增配置字段:
|
||||
|
||||
```python
|
||||
LANGSMITH_TRACING: bool = False
|
||||
LANGSMITH_API_KEY: str = ""
|
||||
LANGSMITH_PROJECT: str = "jarvis-agent"
|
||||
```
|
||||
|
||||
创建 `backend/app/config_tracing.py` 作为独立的 callback 工厂模块:
|
||||
|
||||
```python
|
||||
from langchain_core.callbacks import LangChainTracer
|
||||
from app.config import settings
|
||||
|
||||
def get_langsmith_callbacks() -> list:
|
||||
if not settings.LANGSMITH_TRACING or not settings.LANGSMITH_API_KEY:
|
||||
return []
|
||||
return [LangChainTracer(project_name=settings.LANGSMITH_PROJECT)]
|
||||
```
|
||||
|
||||
#### 2.5.2 Graph 层
|
||||
|
||||
在 `backend/app/agents/graph.py` 中:
|
||||
|
||||
1. `create_agent_graph()` 新增 `callbacks` 参数,透传给 `graph.compile(callbacks=...)`
|
||||
2. `get_agent_graph()` 内部调用 `get_langsmith_callbacks()` 并与传入参数合并后传给 `create_agent_graph()`
|
||||
|
||||
LangGraph 的 `compile(callbacks=...)` 会自动将 callbacks 传播到所有节点的 LLM 调用,覆盖 Master/Planner/Executor/Librarian/Analyst 全部 5 个节点。
|
||||
|
||||
### 2.6 Streaming 兼容性
|
||||
|
||||
当前 streaming 通过 `graph.astream_events()` 实现。LangSmith Callback 会异步记录追踪数据,不影响流式输出的实时性。
|
||||
|
||||
如果需要在 streaming 过程中实时展示 trace URL,可以在 `on_chat_model_end` 事件中从 `run.id` 生成链接:
|
||||
|
||||
```python
|
||||
async for event in graph.astream_events(...):
|
||||
if event["event"] == "on_chat_model_end":
|
||||
run_id = event["data"]["output"].id # 从 response 中获取 run_id
|
||||
trace_url = f"https://smith.langchain.com/runs/{run_id}"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 文件变更清单
|
||||
|
||||
| 文件 | 变更类型 |
|
||||
|---|---|
|
||||
| `backend/.env.example` | 新增 3 行环境变量 |
|
||||
| `backend/pyproject.toml` | 新增 langsmith 依赖 |
|
||||
| `backend/app/config.py` | 新增 3 个配置字段 |
|
||||
| `backend/app/config_tracing.py` | 新建,callback 工厂函数 |
|
||||
| `backend/app/agents/graph.py` | `create_agent_graph`/`get_agent_graph` 支持 callbacks |
|
||||
| `backend/app/services/agent_service.py` | `get_agent_graph()` 调用签名对齐 |
|
||||
|
||||
---
|
||||
|
||||
## 4. 风险与限制
|
||||
|
||||
- LangSmith 免费版有追踪数量限制(详见 LangSmith 定价)
|
||||
- Streaming 模式下 trace 数据在调用结束后才完整展示
|
||||
- 需要用户自行在 [langchain.com](https://smith.langchain.com) 注册并获取 API Key
|
||||
|
||||
---
|
||||
|
||||
## 5. 测试验证
|
||||
|
||||
集成完成后通过以下方式验证:
|
||||
|
||||
1. 设置 `LANGSMITH_TRACING=true` 并配置 API Key
|
||||
2. 发起一次 Agent 对话
|
||||
3. 在 LangSmith Dashboard 中查看对应的 trace,确认包含:
|
||||
- 5 个节点的执行记录
|
||||
- 每个节点的 LLM 输入/输出
|
||||
- 工具调用记录
|
||||
- Token 消耗统计
|
||||
249
docs/superpowers/specs/2026-03-20-settings-register-design.md
Normal file
249
docs/superpowers/specs/2026-03-20-settings-register-design.md
Normal file
@@ -0,0 +1,249 @@
|
||||
# 注册界面 + 设置界面 功能设计
|
||||
|
||||
## 概述
|
||||
|
||||
为 Jarvis 系统添加用户注册功能和完整的设置界面。用户可以:
|
||||
- 在前端注册账号
|
||||
- 在设置界面管理个人信息和 LLM 配置
|
||||
- 配置定时任务等系统参数
|
||||
|
||||
**核心价值:** 支持多用户、每个用户独立配置自己的 LLM 提供商和参数。
|
||||
|
||||
## 现状分析
|
||||
|
||||
### 已有的功能
|
||||
- 后端已有 `/api/auth/register` API
|
||||
- 后端使用 `pydantic-settings` 从 `.env` 读取配置
|
||||
- 前端只有登录页面,无注册入口
|
||||
|
||||
### 需要改动的地方
|
||||
- 前端 LoginView 添加注册表单
|
||||
- User 模型增加 `llm_config` 和 `scheduler_config` JSON 字段
|
||||
- 新建 Settings 路由和服务
|
||||
- 新建 SettingsView 页面
|
||||
|
||||
## 数据模型
|
||||
|
||||
### User 表扩展
|
||||
|
||||
```sql
|
||||
ALTER TABLE users ADD COLUMN llm_config TEXT;
|
||||
ALTER TABLE users ADD COLUMN scheduler_config TEXT;
|
||||
```
|
||||
|
||||
### 字段结构
|
||||
|
||||
**llm_config (JSON):**
|
||||
```json
|
||||
{
|
||||
"chat": {
|
||||
"provider": "openai|claude|ollama|deepseek|custom",
|
||||
"model": "gpt-4o",
|
||||
"base_url": "https://api.openai.com/v1",
|
||||
"api_key": "sk-..."
|
||||
},
|
||||
"vlm": {
|
||||
"provider": "openai",
|
||||
"model": "gpt-4o",
|
||||
"base_url": "...",
|
||||
"api_key": "..."
|
||||
},
|
||||
"embedding": {
|
||||
"provider": "openai",
|
||||
"model": "text-embedding-3-small",
|
||||
"base_url": "...",
|
||||
"api_key": "..."
|
||||
},
|
||||
"rerank": {
|
||||
"provider": "openai",
|
||||
"model": "bge-reranker-v2",
|
||||
"base_url": "...",
|
||||
"api_key": "..."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**scheduler_config (JSON):**
|
||||
```json
|
||||
{
|
||||
"daily_plan_time": "08:00",
|
||||
"forum_scan_interval_minutes": 30,
|
||||
"todo_ai_generate_time": "08:00",
|
||||
"enabled": true
|
||||
}
|
||||
```
|
||||
|
||||
## API 设计
|
||||
|
||||
### 1. 注册 API (已有)
|
||||
```
|
||||
POST /api/auth/register
|
||||
Body: { email, password, full_name }
|
||||
Response: UserOut
|
||||
```
|
||||
|
||||
### 2. 获取用户设置
|
||||
```
|
||||
GET /api/settings
|
||||
Response: {
|
||||
profile: { id, email, full_name, created_at },
|
||||
llm_config: { ... },
|
||||
scheduler_config: { ... }
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 更新用户资料
|
||||
```
|
||||
PUT /api/settings/profile
|
||||
Body: { full_name?, password? }
|
||||
Response: UserOut
|
||||
```
|
||||
|
||||
### 4. 更新 LLM 配置
|
||||
```
|
||||
PUT /api/settings/llm
|
||||
Body: { chat?: {...}, vlm?: {...}, embedding?: {...}, rerank?: {...} }
|
||||
Response: { llm_config: { ... } } // 返回更新后的完整配置
|
||||
```
|
||||
|
||||
### 5. 测试 LLM 连接
|
||||
```
|
||||
POST /api/settings/llm/test
|
||||
Body: { type: "chat"|"vlm"|"embedding"|"rerank", provider, model, base_url, api_key }
|
||||
Response: { success: true, message: "连接成功" } 或 { success: false, error: "错误信息" }
|
||||
```
|
||||
|
||||
### 6. 更新定时任务配置
|
||||
```
|
||||
PUT /api/settings/scheduler
|
||||
Body: { daily_plan_time?, forum_scan_interval_minutes?, todo_ai_generate_time?, enabled? }
|
||||
Response: { scheduler_config: { ... } } // 返回更新后的完整配置
|
||||
```
|
||||
|
||||
## 前端页面
|
||||
|
||||
### LoginView.vue 改动
|
||||
- 添加"注册"和"登录"切换 Tab
|
||||
- 注册表单:邮箱、密码、确认密码、用户名
|
||||
- 复用现有 sci-fi 登录风格
|
||||
|
||||
### SettingsView.vue (新建)
|
||||
|
||||
#### 页面布局
|
||||
```
|
||||
┌─────────────────────────────────────────────────┐
|
||||
│ [⚙] SETTINGS │
|
||||
├─────────────────────────────────────────────────┤
|
||||
│ ┌─────────────────────────────────────────────┐ │
|
||||
│ │ PROFILE │ │
|
||||
│ │ Email: operator@jarvis.ai │ │
|
||||
│ │ Name: [___________] │ │
|
||||
│ │ Password: [********] [Change] │ │
|
||||
│ └─────────────────────────────────────────────┘ │
|
||||
│ ┌─────────────────────────────────────────────┐ │
|
||||
│ │ LLM CONFIGURATION │ │
|
||||
│ │ ┌─ Chat ────────────────────────────────┐ │ │
|
||||
│ │ │ Provider: [OpenAI ▼] │ │ │
|
||||
│ │ │ Model: [gpt-4o ____________] │ │ │
|
||||
│ │ │ Base URL:[https://...] ] │ │ │
|
||||
│ │ │ API Key: [•••••••••••••••••] │ │ │
|
||||
│ │ └──────────────────────────────────────┘ │ │
|
||||
│ │ ┌─ VLM ─────────────────────────────────┐ │ │
|
||||
│ │ │ ... (同上结构) │ │ │
|
||||
│ │ └──────────────────────────────────────┘ │ │
|
||||
│ │ ┌─ Embedding ───────────────────────────┐ │ │
|
||||
│ │ │ ... (同上结构) │ │ │
|
||||
│ │ └──────────────────────────────────────┘ │ │
|
||||
│ │ ┌─ Rerank ──────────────────────────────┐ │ │
|
||||
│ │ │ ... (同上结构) │ │ │
|
||||
│ │ └──────────────────────────────────────┘ │ │
|
||||
│ └─────────────────────────────────────────────┘ │
|
||||
│ ┌─────────────────────────────────────────────┐ │
|
||||
│ │ SCHEDULER │ │
|
||||
│ │ Daily Plan Time: [08:00] │ │
|
||||
│ │ Forum Scan Interval: [30] 分钟 │ │
|
||||
│ │ Todo AI Generate: [08:00] │ │
|
||||
│ │ Scheduler Enabled: [ON] │ │
|
||||
│ └─────────────────────────────────────────────┘ │
|
||||
│ ┌─────────────────────────────────────────────┐ │
|
||||
│ │ [SAVE ALL SETTINGS] │ │
|
||||
│ └─────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
#### 交互行为
|
||||
- 修改后点击"保存"按钮,按钮显示 loading 状态
|
||||
- 保存成功显示 toast 提示"保存成功"
|
||||
- 保存失败显示 toast 提示错误信息
|
||||
- 密码修改需二次确认弹窗
|
||||
- API Key 字段支持显示/隐藏切换
|
||||
- 每个模型配置卡片有独立的"测试"按钮
|
||||
- Provider 切换时自动填充默认值(如 Ollama 切换到 localhost:11434)
|
||||
- Scheduler enabled 关闭时,时间输入框显示禁用状态
|
||||
- 空配置时显示"点击配置"占位提示
|
||||
|
||||
#### 注册表单
|
||||
- 邮箱:必填,格式校验
|
||||
- 用户名:必填,2-20 字符
|
||||
- 密码:必填,最少 8 字符
|
||||
- 确认密码:必填,需与密码一致
|
||||
- 密码强度指示器(弱/中/强)
|
||||
|
||||
## 路由和侧边栏
|
||||
|
||||
### router/index.ts
|
||||
```typescript
|
||||
{
|
||||
path: 'settings',
|
||||
name: 'settings',
|
||||
component: () => import('@/views/SettingsView.vue'),
|
||||
}
|
||||
```
|
||||
|
||||
### SidebarNav.vue
|
||||
```typescript
|
||||
{ name: '设置', path: '/settings', icon: Settings }
|
||||
```
|
||||
|
||||
## 技术实现
|
||||
|
||||
### 后端文件
|
||||
```
|
||||
backend/app/
|
||||
models/
|
||||
user.py # 修改:添加 llm_config, scheduler_config 字段
|
||||
schemas/
|
||||
auth.py # 修改:UserCreate 支持 full_name
|
||||
settings.py # 新建:SettingsOut, LLMConfigIn, SchedulerConfigIn
|
||||
routers/
|
||||
settings.py # 新建:settings router
|
||||
services/
|
||||
settings_service.py # 新建:设置逻辑服务
|
||||
```
|
||||
|
||||
### 前端文件
|
||||
```
|
||||
frontend/src/
|
||||
api/
|
||||
settings.ts # 新建:settings API 客户端
|
||||
views/
|
||||
LoginView.vue # 修改:添加注册 Tab
|
||||
SettingsView.vue # 新建:设置页面
|
||||
router/
|
||||
index.ts # 修改:添加 /settings 路由
|
||||
components/
|
||||
SidebarNav.vue # 修改:添加设置菜单
|
||||
```
|
||||
|
||||
## 验证清单
|
||||
|
||||
1. 注册功能正常 - 可以通过注册页面创建新账号
|
||||
2. 登录功能正常 - 新老用户都可以登录
|
||||
3. 设置页面可访问 - 登录后可进入设置页面
|
||||
4. 个人信息修改正常 - 用户名、密码可修改
|
||||
5. LLM 配置保存正常 - 四种模型配置可保存
|
||||
6. LLM 测试连接正常 - 可以验证配置是否正确
|
||||
7. 定时任务配置正常 - 时间间隔可修改
|
||||
8. 配置持久化正常 - 重新登录后配置保留
|
||||
9. UI 风格一致 - 设置页面与其他页面风格统一
|
||||
10. 注册表单验证正常 - 密码强度、格式校验有效
|
||||
267
docs/superpowers/specs/2026-03-20-stats-dashboard-design.md
Normal file
267
docs/superpowers/specs/2026-03-20-stats-dashboard-design.md
Normal file
@@ -0,0 +1,267 @@
|
||||
# 数据统计页面重新设计
|
||||
|
||||
## 1. 概述与目标
|
||||
|
||||
重新设计数据统计页面,使其与项目现有的深色赛博朋克/终端风格保持一致。采用单页垂直滚动布局,集成迷你图表,提供清晰的数据可视化。
|
||||
|
||||
## 2. 设计语言
|
||||
|
||||
### 视觉风格
|
||||
- **主题**:深色赛博朋克 + 终端美学
|
||||
- **背景**:`var(--bg-void)` 深空黑
|
||||
- **强调色**:青色 `#00f5d4` (现有变量 `var(--accent-cyan)`)
|
||||
- **辅助色**:紫色 `#a855f7` (用于知识库等模块)
|
||||
- **卡片背景**:`rgba(13,21,37,0.8)` 半透明深蓝
|
||||
- **边框**:`1px solid var(--border-dim)`,hover时发光
|
||||
|
||||
### 字体
|
||||
- **数字**:等宽字体 `var(--font-mono)`,大号加粗,带发光效果
|
||||
- **标签**:`var(--font-display)`,9-10px,字母间距 0.15em
|
||||
- **正文**:`var(--font-mono)`,12-13px
|
||||
|
||||
### 动效
|
||||
- 卡片 hover:边框发光 + 微弱上浮
|
||||
- 数字:首次加载时淡入
|
||||
- 图表:绘制动画 300ms
|
||||
|
||||
## 3. 页面结构
|
||||
|
||||
### 单页垂直滚动布局(无 Tabs)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
│ // DATA METRICS [页面标题] │
|
||||
├─────────────────────────────────────────────────────┤
|
||||
│ [SYSTEM HEALTH] 系统健康模块 │
|
||||
│ [CONVERSATIONS] 对话统计模块 │
|
||||
│ [KNOWLEDGE] 知识库模块 │
|
||||
│ [KANBAN] 看板模块 │
|
||||
│ [COMMUNITY] 社区模块 │
|
||||
│ [INSIGHTS] 个人洞察模块 │
|
||||
└─────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 4. 模块详细设计
|
||||
|
||||
### 4.1 系统健康 (SYSTEM HEALTH)
|
||||
|
||||
**位置**:页面最顶部,无需认证即可访问
|
||||
|
||||
**卡片布局**:4列网格
|
||||
|
||||
**指标卡片**:
|
||||
| 指标 | 图标 | 格式 |
|
||||
|------|------|------|
|
||||
| CPU 使用率 | Cpu | 45% + 7天迷你柱状图 |
|
||||
| 内存占用 | MemoryStick | 62% + 7天迷你柱状图 |
|
||||
| 磁盘使用 | HardDrive | 38% + 7天迷你柱状图 |
|
||||
| 运行时间 | Clock | 7d 3h 20m |
|
||||
|
||||
**卡片样式**:
|
||||
- 尺寸:自适应,最小 160px
|
||||
- 数字大小:24px,等宽加粗
|
||||
- 趋势图:高度 24px,7个数据点
|
||||
- 标签:9px,letter-spacing 0.15em
|
||||
|
||||
### 4.2 对话统计 (CONVERSATIONS)
|
||||
|
||||
**需要认证**
|
||||
|
||||
**顶部汇总**:横排4个数字卡片
|
||||
| 指标 | 值 |
|
||||
|------|-----|
|
||||
| 总对话数 | 1,234 |
|
||||
| 总消息数 | 5,678 |
|
||||
| Input Tokens | 12.5M |
|
||||
| Output Tokens | 45.2M |
|
||||
|
||||
**图表**:30天趋势迷你折线图
|
||||
- 4条线:对话数、消息数、Input Token、Output Token
|
||||
- 图例在图表下方
|
||||
- 图表高度:120px
|
||||
- 颜色使用主题色
|
||||
|
||||
### 4.3 知识库 (KNOWLEDGE)
|
||||
|
||||
**需要认证**
|
||||
|
||||
**顶部汇总**:
|
||||
| 指标 | 值 |
|
||||
|------|-----|
|
||||
| 新建标签 | 156 |
|
||||
| 文档数 | 89 |
|
||||
| 标签关系 | 423 |
|
||||
|
||||
**图表**:30天趋势迷你折线图
|
||||
- 3条线:新建标签、文档、标签关系
|
||||
- 使用紫色系 `var(--accent-purple)`
|
||||
|
||||
### 4.4 看板 (KANBAN)
|
||||
|
||||
**需要认证**
|
||||
|
||||
**顶部汇总**:
|
||||
| 指标 | 值 |
|
||||
|------|-----|
|
||||
| 待办任务 | 12 |
|
||||
| 新建任务 | 45 (30天) |
|
||||
| 已完成任务 | 38 (30天) |
|
||||
|
||||
**图表**:30天对比柱状图
|
||||
- 两组柱:新建任务 vs 已完成任务
|
||||
- 使用青色和绿色对比
|
||||
|
||||
### 4.5 社区 (COMMUNITY)
|
||||
|
||||
**需要认证**
|
||||
|
||||
**顶部汇总**:
|
||||
| 指标 | 值 |
|
||||
|------|-----|
|
||||
| 发帖数 | 23 |
|
||||
| 回复数 | 156 |
|
||||
| AI 执行 | 12 |
|
||||
|
||||
**图表**:30天趋势迷你折线图
|
||||
- 3条线:发帖、回复、AI执行
|
||||
|
||||
### 4.6 个人洞察 (INSIGHTS)
|
||||
|
||||
**需要认证**
|
||||
|
||||
**布局**:2列
|
||||
|
||||
**左侧 - 活跃时段**:
|
||||
- 24小时柱状图
|
||||
- 显示高峰时段标记
|
||||
|
||||
**右侧 - Top 标签**:
|
||||
- 列表形式显示前5个常用标签
|
||||
- 显示使用次数
|
||||
|
||||
**Token趋势**:
|
||||
- 本月 vs 上月对比
|
||||
- 百分比变化(带颜色指示上升/下降)
|
||||
|
||||
## 5. 组件清单
|
||||
|
||||
### MetricCard 指标卡片
|
||||
```
|
||||
Props:
|
||||
- icon: Component (lucide图标)
|
||||
- label: string
|
||||
- value: string | number
|
||||
- trend?: number[] (可选,迷你图数据)
|
||||
- accentColor?: string (默认cyan)
|
||||
|
||||
States:
|
||||
- default: 静态显示
|
||||
- hover: 边框发光,轻微上浮
|
||||
- loading: 骨架屏
|
||||
- error: 显示 "--" 和错误图标
|
||||
```
|
||||
|
||||
### MiniLineChart 迷你折线图
|
||||
```
|
||||
Props:
|
||||
- data: { date: string, value: number }[]
|
||||
- color?: string
|
||||
- height?: number (默认40px)
|
||||
|
||||
Features:
|
||||
- 纯CSS实现或tiny echarts
|
||||
- 无坐标轴,仅保留趋势
|
||||
- 数据点过多时自动采样
|
||||
```
|
||||
|
||||
### MiniBarChart 迷你柱状图
|
||||
```
|
||||
Props:
|
||||
- data: number[]
|
||||
- color?: string
|
||||
- height?: number (默认24px)
|
||||
- maxBars?: number (默认7)
|
||||
```
|
||||
|
||||
### SectionHeader 区块标题
|
||||
```
|
||||
Props:
|
||||
- title: string
|
||||
- tag?: 'cyan' | 'purple' | 'amber' (标签颜色)
|
||||
|
||||
Style:
|
||||
- 格式:// SECTION_NAME
|
||||
- 左侧竖线装饰
|
||||
- 标签 Chip 在右侧
|
||||
```
|
||||
|
||||
### SummaryRow 汇总行
|
||||
```
|
||||
Props:
|
||||
- items: { label: string, value: string | number }[]
|
||||
- columns?: number (默认4)
|
||||
```
|
||||
|
||||
## 6. 技术实现
|
||||
|
||||
### 前端
|
||||
- **框架**:Vue 3 + TypeScript (已有)
|
||||
- **图表库**:使用 CSS 实现迷你图,或 echarts (已有)
|
||||
- **图标**:lucide-vue-next (已有)
|
||||
- **状态管理**:Pinia (已有)
|
||||
- **API**:StatsView 中已有 stats API 调用
|
||||
|
||||
### 后端
|
||||
- 复用现有 `app/routers/stats.py` 和 `app/services/stats_service.py`
|
||||
- 确保所有接口正确返回数据
|
||||
|
||||
### 样式
|
||||
- 复用 `ChatView.vue` 中的设计变量和样式模式
|
||||
- 使用 CSS Grid 实现响应式布局
|
||||
- 变量:`--bg-panel`, `--accent-cyan`, `--border-dim`, `--font-mono` 等
|
||||
|
||||
## 7. 响应式断点
|
||||
|
||||
| 设备 | 列数 |
|
||||
|------|------|
|
||||
| >= 1200px | 4列 |
|
||||
| 768px - 1199px | 2列 |
|
||||
| < 768px | 1列 |
|
||||
|
||||
## 8. 错误与空状态
|
||||
|
||||
### Error State
|
||||
- 显示错误图标和文字
|
||||
- 提供刷新按钮
|
||||
- 保持页面结构完整
|
||||
|
||||
### Empty State
|
||||
- 各模块独立空状态
|
||||
- 不阻塞其他模块显示
|
||||
- 友好提示文案
|
||||
|
||||
### Loading State
|
||||
- 骨架屏动画
|
||||
- 与卡片结构一致
|
||||
|
||||
## 9. 访问控制
|
||||
|
||||
| 模块 | 认证要求 | 说明 |
|
||||
|------|----------|------|
|
||||
| 系统健康 | 否 | 所有人可看 |
|
||||
| 对话统计 | 是 | 需登录 |
|
||||
| 知识库 | 是 | 需登录 |
|
||||
| 看板 | 是 | 需登录 |
|
||||
| 社区 | 是 | 需登录 |
|
||||
| 个人洞察 | 是 | 需登录 |
|
||||
|
||||
未登录用户访问需认证模块时:
|
||||
- 显示占位卡片结构
|
||||
- 提示"请先登录"
|
||||
- 不发送无效请求
|
||||
|
||||
## 10. 数据刷新
|
||||
|
||||
- 页面进入时加载所有数据
|
||||
- 支持手动刷新按钮(每个模块独立刷新)
|
||||
- 数字变化时无动画(避免干扰)
|
||||
473
docs/superpowers/specs/2026-03-21-forum-redesign-design.md
Normal file
473
docs/superpowers/specs/2026-03-21-forum-redesign-design.md
Normal file
@@ -0,0 +1,473 @@
|
||||
# 交互广场重新设计
|
||||
|
||||
## 1. 概述与目标
|
||||
|
||||
将现有的论坛(交互广场)从传统的帖子/回复模式,重构为三个AI驱动的智能板块:
|
||||
1. **AI学习板块** - 模型分析用户活动,学习客观知识并加入知识图谱,向用户汇报学习成果
|
||||
2. **AI建议板块** - 基于用户习惯和数据,提供个性化建议
|
||||
3. **AI交互板块** - 用户发起学习主题,或AI主动探索补充知识
|
||||
|
||||
## 2. 设计风格
|
||||
|
||||
沿用项目现有的深色赛博朋克/终端风格:
|
||||
- 背景:`var(--bg-void)` 深空黑
|
||||
- 强调色:紫色 `#a855f7` (用于交互广场专属色调)
|
||||
- 卡片背景:`var(--bg-card)`
|
||||
- 边框:`1px solid var(--border-dim)`,hover时发光
|
||||
- 字体:等宽字体 `var(--font-mono)`,标题用 `var(--font-display)`
|
||||
|
||||
## 3. 页面结构
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ // INTERACTIVE PLAZA [页面标题] │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ [MODEL LEARNING] AI学习板块 │ │
|
||||
│ │ AI分析你的活动,学习知识并汇报 │ │
|
||||
│ ├─────────────────────────────────────────────────────┤ │
|
||||
│ │ • 今日学习摘要 │ │
|
||||
│ │ • 学习历史时间线 │ │
|
||||
│ │ • 知识图谱更新统计 │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ [SUGGESTIONS] AI建议板块 │ │
|
||||
│ │ 基于你的习惯提供个性化建议 │ │
|
||||
│ ├─────────────────────────────────────────────────────┤ │
|
||||
│ │ • 知识补充建议 │ │
|
||||
│ │ • 效率优化建议 │ │
|
||||
│ │ • 技能深耕建议 │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ [INTERACTIVE] AI交互学习板块 │ │
|
||||
│ │ 用户发起学习主题,AI主动探索 │ │
|
||||
│ ├─────────────────────────────────────────────────────┤ │
|
||||
│ │ • 用户发起的学习主题 │ │
|
||||
│ │ • AI主动学习的内容 │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 4. 功能详情
|
||||
|
||||
### 4.1 AI学习板块 (MODEL LEARNING)
|
||||
|
||||
**数据来源:**
|
||||
- 对话记录(`messages` 表,Message模型)- 分析对话内容提取概念
|
||||
- 看板任务(`tasks` 表,Task模型)- 识别技术栈和工作流程
|
||||
- 知识库(`documents`, `kg_nodes` 表)- 补充知识缺口
|
||||
|
||||
**学习流程:**
|
||||
```
|
||||
定时任务触发 → 分析近期活动 → 提取概念/术语/事实
|
||||
→ 存入知识图谱(KGNode) → 生成学习报告 → 存入learning_records表
|
||||
```
|
||||
|
||||
**数据库扩展:**
|
||||
|
||||
```python
|
||||
# 新增 learning_records 表
|
||||
# 继承 app.models.base.BaseModel,自动获得 id, created_at, updated_at
|
||||
from app.models.base import BaseModel
|
||||
|
||||
class LearningRecord(BaseModel):
|
||||
__tablename__ = "learning_records"
|
||||
|
||||
user_id = Column(String(36), ForeignKey("users.id"), nullable=False, index=True)
|
||||
learning_type = Column(String(50), nullable=False) # concept, technology, workflow
|
||||
topic = Column(String(500), nullable=False) # 学习主题
|
||||
summary = Column(Text, nullable=False) # AI生成的学习摘要
|
||||
source = Column(String(50), nullable=False) # conversation, kanban, knowledge
|
||||
source_ids = Column(JSON, nullable=True) # 来源ID列表,如 {conversation_ids: [...], task_ids: [...]}
|
||||
kg_nodes_created = Column(JSON, nullable=True) # 创建的KGNode ID列表
|
||||
```
|
||||
|
||||
**KGNode实体类型扩展:**
|
||||
- `learned_concept` - 从对话中学到的概念
|
||||
- `technology` - 识别出的技术栈
|
||||
- `workflow` - 从看板任务中提取的工作流程
|
||||
|
||||
**前端展示:**
|
||||
|
||||
1. **今日学习摘要卡片**
|
||||
- AI生成的自然语言总结
|
||||
- 示例:"今日学习了依赖注入和异步编程两个概念,它们都来自你关于FastAPI的讨论"
|
||||
- 显示来源标签:对话/看板/知识库
|
||||
|
||||
2. **学习历史时间线**
|
||||
- 垂直时间线布局
|
||||
- 每条记录显示:时间、主题、摘要
|
||||
- 点击展开查看详情
|
||||
|
||||
3. **知识图谱更新统计**
|
||||
- 今日新增节点数
|
||||
- 今日新建关系数
|
||||
- 迷你柱状图显示各类别占比(可复用 MiniBarChart)
|
||||
|
||||
### 4.2 AI建议板块 (SUGGESTIONS)
|
||||
|
||||
**建议类型:**
|
||||
|
||||
1. **知识补充建议 (knowledge)**
|
||||
- 检测知识图谱薄弱领域
|
||||
- 基于用户提问推断知识缺口
|
||||
- 示例:"你的知识图谱在'微服务架构'领域较为薄弱,建议深入学习"
|
||||
|
||||
2. **效率优化建议 (efficiency)**
|
||||
- 分析用户使用模式
|
||||
- 推荐最佳实践
|
||||
- 示例:"你通常在下午工作效率最高,建议将复杂任务安排在这个时段"
|
||||
|
||||
3. **技能深耕建议 (skill)**
|
||||
- 基于高频话题
|
||||
- 推荐深入学习方向
|
||||
- 示例:"你最近频繁讨论API设计,建议学习REST最佳实践和GraphQL"
|
||||
|
||||
**数据库扩展:**
|
||||
|
||||
```python
|
||||
# 新增 suggestions 表
|
||||
from app.models.base import BaseModel
|
||||
|
||||
class Suggestion(BaseModel):
|
||||
__tablename__ = "suggestions"
|
||||
|
||||
user_id = Column(String(36), ForeignKey("users.id"), nullable=False, index=True)
|
||||
suggestion_type = Column(String(50), nullable=False) # knowledge, efficiency, skill
|
||||
title = Column(String(500), nullable=False) # 建议标题
|
||||
content = Column(Text, nullable=False) # 建议内容
|
||||
source_data = Column(JSON, nullable=True) # 分析依据,如 {knowledge_gaps: [...], usage_patterns: {...}}
|
||||
is_read = Column(Boolean, default=False) # 是否已读
|
||||
is_dismissed = Column(Boolean, default=False) # 是否忽略
|
||||
```
|
||||
|
||||
**前端展示:**
|
||||
- 卡片列表布局
|
||||
- 每个建议显示:图标、类型标签、标题、内容
|
||||
- 右侧显示建议来源分析
|
||||
- 提供"查看详情"和"忽略"按钮
|
||||
|
||||
### 4.3 AI交互板块 (INTERACTIVE)
|
||||
|
||||
**用户发起学习:**
|
||||
|
||||
1. 用户输入想学习的主题
|
||||
2. AI分析主题,搜索知识库
|
||||
3. 如有需要,AI主动抓取外部资源
|
||||
4. 生成学习报告
|
||||
5. 自动存入知识图谱
|
||||
6. 在交互板块展示
|
||||
|
||||
**数据库扩展:**
|
||||
|
||||
```python
|
||||
# 新增 interactive_topics 表
|
||||
from app.models.base import BaseModel
|
||||
|
||||
class InteractiveTopic(BaseModel):
|
||||
__tablename__ = "interactive_topics"
|
||||
|
||||
user_id = Column(String(36), ForeignKey("users.id"), nullable=False, index=True)
|
||||
topic = Column(String(500), nullable=False) # 学习主题
|
||||
status = Column(String(50), nullable=False) # pending, learning, completed, failed
|
||||
result = Column(Text, nullable=True) # 学习结果/报告
|
||||
kg_nodes_created = Column(JSON, nullable=True) # 创建的KGNode ID列表
|
||||
source = Column(String(50), nullable=False) # user_initiated, ai_proactive
|
||||
completed_at = Column(DateTime, nullable=True)
|
||||
```
|
||||
|
||||
**AI主动学习:**
|
||||
|
||||
1. AI分析用户历史提问
|
||||
2. 发现知识缺口或关联主题
|
||||
3. 主动学习并生成报告
|
||||
4. 在交互板块标记为"AI主动"
|
||||
|
||||
**前端展示:**
|
||||
- 两个子区块:用户发起 / AI主动
|
||||
- 输入框:"让AI学习 [主题]"
|
||||
- 正在进行的学习任务显示进度
|
||||
- 已完成的学习显示结果摘要
|
||||
|
||||
## 5. API 设计
|
||||
|
||||
### 5.1 后端接口
|
||||
|
||||
```
|
||||
GET /api/forum/learning/summary
|
||||
- 获取今日学习摘要
|
||||
- 返回: { summary, records[], stats{ nodes_created, edges_created } }
|
||||
|
||||
GET /api/forum/learning/history?page=1&limit=20
|
||||
- 获取学习历史
|
||||
- 返回: { records[], total }
|
||||
|
||||
GET /api/forum/suggestions
|
||||
- 获取所有建议
|
||||
- 返回: { suggestions[] }
|
||||
|
||||
GET /api/forum/suggestions/{id}
|
||||
- 获取单个建议详情
|
||||
- 返回: Suggestion
|
||||
|
||||
PATCH /api/forum/suggestions/{id}/read
|
||||
- 标记建议为已读
|
||||
|
||||
DELETE /api/forum/suggestions/{id}/dismiss
|
||||
- 忽略/删除建议
|
||||
|
||||
GET /api/forum/interactive/topics
|
||||
- 获取交互主题列表
|
||||
- 返回: { user_initiated[], ai_proactive[] }
|
||||
|
||||
POST /api/forum/interactive/learn
|
||||
- 用户发起学习
|
||||
- Body: { topic: string }
|
||||
- 返回: { topic_id, status }
|
||||
|
||||
GET /api/forum/interactive/topics/{id}
|
||||
- 获取学习主题详情/结果
|
||||
```
|
||||
|
||||
### 5.2 前端API
|
||||
|
||||
```typescript
|
||||
// TypeScript 类型定义
|
||||
interface LearningSummary {
|
||||
summary: string
|
||||
records: LearningRecord[]
|
||||
stats: {
|
||||
nodes_created: number
|
||||
edges_created: number
|
||||
}
|
||||
}
|
||||
|
||||
interface LearningRecord {
|
||||
id: string
|
||||
learning_type: 'concept' | 'technology' | 'workflow'
|
||||
topic: string
|
||||
summary: string
|
||||
source: string
|
||||
source_ids?: { conversation_ids?: string[]; task_ids?: string[] }
|
||||
kg_nodes_created?: string[]
|
||||
created_at: string
|
||||
}
|
||||
|
||||
interface Suggestion {
|
||||
id: string
|
||||
suggestion_type: 'knowledge' | 'efficiency' | 'skill'
|
||||
title: string
|
||||
content: string
|
||||
source_data?: Record<string, any>
|
||||
is_read: boolean
|
||||
is_dismissed: boolean
|
||||
created_at: string
|
||||
}
|
||||
|
||||
interface InteractiveTopic {
|
||||
id: string
|
||||
topic: string
|
||||
status: 'pending' | 'learning' | 'completed' | 'failed'
|
||||
result?: string
|
||||
kg_nodes_created?: string[]
|
||||
source: 'user_initiated' | 'ai_proactive'
|
||||
created_at: string
|
||||
completed_at?: string
|
||||
}
|
||||
|
||||
// API 方法
|
||||
const forumApi = {
|
||||
// learning
|
||||
fetchLearningSummary(): Promise<LearningSummary>,
|
||||
fetchLearningHistory(params: { page: number, limit: number }): Promise<{ records: LearningRecord[], total: number }>,
|
||||
|
||||
// suggestions
|
||||
fetchSuggestions(): Promise<Suggestion[]>,
|
||||
getSuggestion(id: string): Promise<Suggestion>,
|
||||
markSuggestionRead(id: string): Promise<void>,
|
||||
dismissSuggestion(id: string): Promise<void>,
|
||||
|
||||
// interactive
|
||||
fetchInteractiveTopics(): Promise<{ user_initiated: InteractiveTopic[], ai_proactive: InteractiveTopic[] }>,
|
||||
initiateLearning(topic: string): Promise<InteractiveTopic>,
|
||||
getTopicDetail(id: string): Promise<InteractiveTopic>,
|
||||
}
|
||||
```
|
||||
|
||||
## 6. 组件结构
|
||||
|
||||
```
|
||||
frontend/src/views/ForumView.vue # 主页面,三板块布局
|
||||
frontend/src/components/forum/
|
||||
├── LearningSection.vue # AI学习板块
|
||||
│ ├── LearningSummaryCard.vue # 今日摘要卡片
|
||||
│ ├── LearningTimeline.vue # 学习历史时间线
|
||||
│ └── LearningStats.vue # 图谱更新统计(复用MiniBarChart)
|
||||
├── SuggestionSection.vue # AI建议板块
|
||||
│ ├── SuggestionCard.vue # 建议卡片
|
||||
│ └── SuggestionList.vue # 建议列表
|
||||
└── InteractiveSection.vue # AI交互板块
|
||||
├── LearningInput.vue # 学习主题输入框
|
||||
├── UserInitiatedList.vue # 用户发起列表
|
||||
└── AIProactiveList.vue # AI主动列表
|
||||
|
||||
# 新增通用组件
|
||||
frontend/src/components/forum/MiniDonutChart.vue # 环形图(用于知识类别占比)
|
||||
```
|
||||
|
||||
## 7. 服务层
|
||||
|
||||
### 7.1 LearningService
|
||||
|
||||
```python
|
||||
from app.core.llm import get_llm_client
|
||||
|
||||
class LearningService:
|
||||
def __init__(self, db: AsyncSession):
|
||||
self.llm = get_llm_client()
|
||||
|
||||
async def generate_daily_summary(user_id: str) -> str:
|
||||
"""分析用户今日活动,生成学习摘要"""
|
||||
# 使用 LLM 分析提取的概念,生成自然语言摘要
|
||||
concepts = await self.extract_concepts(...)
|
||||
prompt = f"根据以下学习内容生成简短摘要:{concepts}"
|
||||
return await self.llm.chat(prompt)
|
||||
|
||||
async def extract_concepts_from_conversations(user_id: str, since: datetime) -> list[dict]:
|
||||
"""从对话中提取概念"""
|
||||
|
||||
async def identify_technologies_from_kanban(user_id: str) -> list[dict]:
|
||||
"""从看板任务中识别技术栈"""
|
||||
|
||||
async def create_kg_nodes(user_id: str, learnings: list[dict]) -> list[str]:
|
||||
"""创建知识图谱节点"""
|
||||
|
||||
async def record_learning(...) -> LearningRecord:
|
||||
"""记录学习成果"""
|
||||
```
|
||||
|
||||
### 7.2 SuggestionService
|
||||
|
||||
```python
|
||||
class SuggestionService:
|
||||
def __init__(self, db: AsyncSession):
|
||||
self.llm = get_llm_client()
|
||||
|
||||
async def generate_suggestions(user_id: str) -> list[Suggestion]:
|
||||
"""生成个性化建议"""
|
||||
# 分析知识缺口、使用模式、技能机会
|
||||
gaps = await self.analyze_knowledge_gaps(user_id)
|
||||
patterns = await self.analyze_usage_patterns(user_id)
|
||||
skills = await self.analyze_skill_opportunities(user_id)
|
||||
|
||||
# 使用 LLM 生成建议
|
||||
prompt = f"基于以下分析生成建议:知识缺口{gaps},使用模式{patterns},技能机会{skills}"
|
||||
return await self.llm.chat(prompt)
|
||||
|
||||
async def analyze_knowledge_gaps(user_id: str) -> list[dict]:
|
||||
"""分析知识图谱缺口"""
|
||||
|
||||
async def analyze_usage_patterns(user_id: str) -> dict:
|
||||
"""分析使用模式"""
|
||||
|
||||
async def identify_skill_opportunities(user_id: str) -> list[dict]:
|
||||
"""识别技能提升机会"""
|
||||
```
|
||||
|
||||
### 7.3 InteractiveService
|
||||
|
||||
```python
|
||||
class InteractiveService:
|
||||
def __init__(self, db: AsyncSession):
|
||||
self.llm = get_llm_client()
|
||||
|
||||
async def initiate_learning(user_id: str, topic: str) -> InteractiveTopic:
|
||||
"""用户发起学习"""
|
||||
|
||||
async def execute_learning(topic_id: str) -> dict:
|
||||
"""执行学习任务:
|
||||
1. 搜索知识库相关节点
|
||||
2. 使用 LLM 深入学习主题
|
||||
3. 生成学习报告
|
||||
4. 创建 KGNode
|
||||
5. 更新 topic 状态
|
||||
"""
|
||||
topic = await self.get_topic(topic_id)
|
||||
content = await self.research_topic(topic.topic)
|
||||
report = await self.generate_learning_report(topic, content)
|
||||
await self.create_kg_nodes_from_report(report)
|
||||
await self.update_topic_status(topic_id, 'completed', report)
|
||||
|
||||
async def generate_learning_report(self, topic: InteractiveTopic, content: str) -> str:
|
||||
"""使用 LLM 生成结构化学习报告"""
|
||||
```
|
||||
|
||||
## 8. 定时任务
|
||||
|
||||
每日凌晨生成学习报告:
|
||||
- 分析昨日用户活动
|
||||
- 提取新概念和技术栈
|
||||
- 更新知识图谱
|
||||
- 生成学习摘要存入数据库
|
||||
|
||||
**集成方式:** 使用项目现有的 `scheduler_service.py`
|
||||
|
||||
```python
|
||||
# 在 scheduler_service.py 的 start_scheduler() 中添加
|
||||
from app.services.learning_service import LearningService
|
||||
|
||||
async def daily_learning_job():
|
||||
"""每日凌晨0:30生成学习报告"""
|
||||
from app.database import get_db_session
|
||||
|
||||
async for db in get_db_session():
|
||||
service = LearningService(db)
|
||||
users = await get_all_active_users(db)
|
||||
for user in users:
|
||||
await service.generate_and_record_daily_learning(user.id)
|
||||
break
|
||||
|
||||
# 在 start_scheduler() 中注册
|
||||
scheduler.add_job(daily_learning_job, "cron", hour=0, minute=30, id="daily_learning")
|
||||
```
|
||||
|
||||
## 9. 错误处理
|
||||
|
||||
| 场景 | 处理 |
|
||||
|------|------|
|
||||
| 无活动数据 | 显示"今日暂无学习成果",不生成空记录 |
|
||||
| 知识图谱更新失败 | 回滚学习记录,标记为失败状态 |
|
||||
| AI生成失败 | 记录原始数据,标记需要重试 |
|
||||
| 用户发起学习主题为空 | 前端验证拦截,不发送请求 |
|
||||
|
||||
## 10. 访问控制
|
||||
|
||||
所有板块需要用户登录后访问:
|
||||
- 未登录用户显示"请先登录"提示
|
||||
- 不发送无效API请求
|
||||
- 保持页面结构完整
|
||||
|
||||
## 11. 技术实现
|
||||
|
||||
**前端:**
|
||||
- Vue 3 + TypeScript
|
||||
- 复用现有组件样式(StatsView.vue模式)
|
||||
- CSS实现迷你图表
|
||||
- lucide-vue-next图标
|
||||
|
||||
**后端:**
|
||||
- FastAPI + SQLAlchemy
|
||||
- 复用现有数据库连接
|
||||
- 新增三个Service类
|
||||
- 复用现有认证机制
|
||||
|
||||
**数据流:**
|
||||
```
|
||||
用户活动 → LearningService分析 → KGNode创建 → LearningRecord存储
|
||||
↓
|
||||
AI生成摘要 → 前端展示
|
||||
```
|
||||
307
docs/superpowers/specs/2026-03-21-knowledge-folder-design.md
Normal file
307
docs/superpowers/specs/2026-03-21-knowledge-folder-design.md
Normal file
@@ -0,0 +1,307 @@
|
||||
# 知识库文件夹分层设计
|
||||
|
||||
> **Goal:** 为知识库添加文件夹分层组织功能,支持多层嵌套、CRUD 操作,支持知识大脑汇聚各类内容。
|
||||
|
||||
## 1. 概念与愿景
|
||||
|
||||
知识库是用户的**资料中枢**,文件夹分层让知识更有序。用户可以按主题/项目/类型建立文件夹层级,如 `技术文档/Python/入门.pdf`。
|
||||
|
||||
知识大脑会汇聚来自知识库、待办、看板、论坛、对话的内容,形成完整的用户知识画像。文件夹是知识的入口分类,而非知识图谱的一部分。
|
||||
|
||||
## 2. 数据模型
|
||||
|
||||
### 2.1 Folder 表(邻接表模式)
|
||||
|
||||
```python
|
||||
class Folder(BaseModel):
|
||||
__tablename__ = "folders"
|
||||
|
||||
user_id = Column(String(36), ForeignKey("users.id"), nullable=False, index=True)
|
||||
name = Column(String(255), nullable=False)
|
||||
parent_id = Column(String(36), ForeignKey("folders.id"), nullable=True) # NULL=根目录
|
||||
# 注意: id, created_at, updated_at 继承自 BaseModel
|
||||
```
|
||||
|
||||
**特点:**
|
||||
- 邻接表模式:通过 `parent_id` 指向父文件夹
|
||||
- 根目录文件夹的 `parent_id = NULL`
|
||||
- 查询完整树结构使用递归 CTE
|
||||
- **唯一约束**:`user_id + parent_id + name` 组合唯一,防止同级重名
|
||||
|
||||
**验证规则:**
|
||||
- 文件夹名称不能为空,最大 255 字符
|
||||
- 不允许包含字符:`/ \ * ? :`
|
||||
- 最大嵌套深度:10 层(防止 UI/性能问题)
|
||||
|
||||
### 2.2 Document 表变更
|
||||
|
||||
```python
|
||||
class Document(BaseModel):
|
||||
# ...现有字段...
|
||||
folder_id = Column(String(36), ForeignKey("folders.id"), nullable=True) # 新增
|
||||
```
|
||||
|
||||
**约定:**
|
||||
- `folder_id = NULL` 表示文档在根目录(未分类)
|
||||
- 删除文件夹时,级联删除该文件夹及其所有子文件夹中的文档
|
||||
|
||||
### 2.3 ChromaDB Metadata
|
||||
|
||||
```python
|
||||
{
|
||||
"document_id": "xxx",
|
||||
"document_title": "入门.pdf",
|
||||
"folder_path": "/技术文档/Python", # 完整路径,用于检索过滤
|
||||
"file_type": "pdf",
|
||||
"chunk_index": 0,
|
||||
}
|
||||
```
|
||||
|
||||
## 3. API 接口
|
||||
|
||||
### 3.1 文件夹管理
|
||||
|
||||
| 方法 | 路径 | 说明 |
|
||||
|------|------|------|
|
||||
| GET | `/api/folders` | 获取用户的完整文件夹树 |
|
||||
| POST | `/api/folders` | 创建文件夹 `{ name, parent_id? }` |
|
||||
| PUT | `/api/folders/{id}` | 重命名文件夹 `{ name }` |
|
||||
| DELETE | `/api/folders/{id}` | 删除文件夹(级联删除文档) |
|
||||
|
||||
**GET /api/folders 响应:**
|
||||
```json
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"id": "xxx",
|
||||
"name": "技术文档",
|
||||
"parent_id": null,
|
||||
"children": [
|
||||
{
|
||||
"id": "yyy",
|
||||
"name": "Python",
|
||||
"parent_id": "xxx",
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 文档管理变更
|
||||
|
||||
| 方法 | 路径 | 说明 |
|
||||
|------|------|------|
|
||||
| GET | `/api/documents?folder_id=` | 按文件夹查询文档 |
|
||||
| POST | `/api/documents` | 上传文档时指定 `folder_id` |
|
||||
| DELETE | `/api/documents/{id}` | 删除文档 |
|
||||
|
||||
**POST /api/documents 请求增加可选字段:**
|
||||
```json
|
||||
{
|
||||
"file": "<binary>",
|
||||
"folder_id": "yyy" // 可选,不传表示根目录
|
||||
}
|
||||
```
|
||||
|
||||
### 3.3 安全与权限
|
||||
|
||||
**所有权验证:**
|
||||
- 所有文件夹操作必须验证 `folder.user_id == current_user.id`
|
||||
- 文档操作时验证 `document.user_id == current_user.id`
|
||||
- `folder_id` 参数需要验证归属,防止跨用户访问
|
||||
|
||||
**示例中间件:**
|
||||
```python
|
||||
async def verify_folder_access(folder_id: str, user_id: str, db: AsyncSession):
|
||||
result = await db.execute(
|
||||
select(Folder).where(Folder.id == folder_id, Folder.user_id == user_id)
|
||||
)
|
||||
if not result.scalar_one_or_none():
|
||||
raise HTTPException(status_code=403, detail="无权访问此文件夹")
|
||||
```
|
||||
|
||||
### 3.4 向量检索变更
|
||||
|
||||
`KnowledgeService.retrieve()` 增加可选参数 `folder_id`:
|
||||
|
||||
```python
|
||||
async def retrieve(
|
||||
self,
|
||||
query: str,
|
||||
user_id: str,
|
||||
folder_id: str | None = None, # 新增
|
||||
top_k: int = 5,
|
||||
):
|
||||
# 如果指定 folder_id,构建 path 前缀过滤
|
||||
folder_path = await self._get_folder_path(folder_id)
|
||||
where = {"folder_path": {"$starts_with": folder_path}} if folder_path else None
|
||||
```
|
||||
|
||||
### 3.5 ChromaDB 同步策略
|
||||
|
||||
**文件夹重命名/移动时的同步:**
|
||||
|
||||
由于 ChromaDB metadata 中存储了 `folder_path`,当文件夹路径变化时需要同步更新:
|
||||
|
||||
```python
|
||||
async def update_folder_paths(folder_id: str, old_path: str, new_path: str):
|
||||
"""更新所有子文件夹和文档的路径"""
|
||||
# 1. 更新所有子文件夹的 path
|
||||
children = await db.execute(
|
||||
select(Folder).where(Folder.parent_id == folder_id)
|
||||
)
|
||||
for child in children.scalars():
|
||||
child_new_path = new_path + "/" + child.name
|
||||
await update_folder_paths(child.id, old_path + "/" + child.name, child_new_path)
|
||||
|
||||
# 2. 更新该文件夹下所有文档的 ChromaDB metadata
|
||||
docs = await db.execute(
|
||||
select(Document).where(Document.folder_id == folder_id)
|
||||
)
|
||||
for doc in docs.scalars():
|
||||
collection.update(
|
||||
where={"document_id": doc.id},
|
||||
set={"folder_path": new_path}
|
||||
)
|
||||
```
|
||||
|
||||
**删除文件夹时的清理:**
|
||||
|
||||
```python
|
||||
async def delete_folder_cascade(folder_id: str):
|
||||
"""级联删除:先删子文件夹,再删文档,最后删自己"""
|
||||
# 1. 递归删除所有子文件夹
|
||||
children = await db.execute(
|
||||
select(Folder).where(Folder.parent_id == folder_id)
|
||||
)
|
||||
for child in children.scalars():
|
||||
await delete_folder_cascade(child.id)
|
||||
|
||||
# 2. 删除该文件夹下所有文档(从 ChromaDB 和数据库)
|
||||
docs = await db.execute(
|
||||
select(Document).where(Document.folder_id == folder_id)
|
||||
)
|
||||
for doc in docs.scalars():
|
||||
await knowledge_service.delete_from_vectorstore(user_id, doc.id)
|
||||
await db.delete(doc)
|
||||
|
||||
# 3. 删除文件夹本身
|
||||
folder = await db.get(Folder, folder_id)
|
||||
await db.delete(folder)
|
||||
```
|
||||
|
||||
## 4. 前端设计
|
||||
|
||||
### 4.1 布局结构
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ KNOWLEDGE BASE [+新建文件夹] [+上传] │
|
||||
├──────────────┬──────────────────────────────────────────┤
|
||||
│ │ │
|
||||
│ 📁 技术文档 │ 搜索栏 [🔍 搜索...] [混合▼] │
|
||||
│ 📁 Python │ │
|
||||
│ 📄 入门 │ ┌─────────────────────────────────┐ │
|
||||
│ 📄 进阶 │ │ 文档标题 │ │
|
||||
│ 📁 Vue │ │ 类型 · 大小 · 状态 │ │
|
||||
│ 📁 产品 │ └─────────────────────────────────┘ │
|
||||
│ │ │
|
||||
│ 📁 临时文件 │ ┌─────────────────────────────────┐ │
|
||||
│ │ │ ... │ │
|
||||
│ │ └─────────────────────────────────┘ │
|
||||
└──────────────┴──────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 4.2 组件结构
|
||||
|
||||
```
|
||||
KnowledgeView
|
||||
├── Header (标题 + 操作按钮)
|
||||
├── MainLayout (flexbox: sidebar + content)
|
||||
│ ├── FolderTree (左侧边栏)
|
||||
│ │ ├── FolderItem (递归组件)
|
||||
│ │ │ ├── folder icon + name
|
||||
│ │ │ ├── children (递归)
|
||||
│ │ │ └── context menu (右键: 重命名/删除)
|
||||
│ │ └── AddFolderButton
|
||||
│ │
|
||||
│ └── ContentArea (右侧主区域)
|
||||
│ ├── SearchBar
|
||||
│ ├── UploadZone
|
||||
│ ├── DocumentList
|
||||
│ └── SearchResults
|
||||
```
|
||||
|
||||
### 4.3 交互细节
|
||||
|
||||
| 操作 | 行为 |
|
||||
|------|------|
|
||||
| 点击文件夹 | 高亮选中,显示该文件夹下文档 |
|
||||
| 右键文件夹 | 弹出菜单:重命名 / 删除 |
|
||||
| 双击文件夹名 | 进入编辑状态 |
|
||||
| 新建文件夹 | 弹出输入框,默认在当前选中位置创建 |
|
||||
| 上传文档 | 需先选择目标文件夹,否则默认根目录 |
|
||||
| 搜索 | 可选限定在当前文件夹内搜索 |
|
||||
|
||||
### 4.4 UI 风格
|
||||
|
||||
保持一致的 sci-fi holographic 风格:
|
||||
- 主色调:青色 `#00f5d4` + 深色背景
|
||||
- 文件夹图标:使用 Folder/FolderOpen 图标
|
||||
- 悬停/选中状态:边框高亮 + 背景色变化
|
||||
- 动画:展开/折叠动画 200ms ease
|
||||
|
||||
## 5. 实施步骤
|
||||
|
||||
### Phase 1: 数据层
|
||||
1. 创建 `Folder` 模型和表
|
||||
2. 修改 `Document` 模型,增加 `folder_id` 外键
|
||||
3. 添加数据库迁移
|
||||
|
||||
### Phase 2: 后端 API
|
||||
1. 实现文件夹 CRUD 接口
|
||||
2. 修改文档上传接口,支持 `folder_id`
|
||||
3. 修改文档列表接口,支持 `folder_id` 过滤
|
||||
4. 修改向量检索,支持 `folder_id` 范围限定
|
||||
5. 实现递归 CTE 查询文件夹树
|
||||
|
||||
**递归 CTE 示例(获取完整文件夹树):**
|
||||
```sql
|
||||
WITH RECURSIVE folder_tree AS (
|
||||
-- 基础查询:根文件夹
|
||||
SELECT id, name, parent_id, 0 as depth
|
||||
FROM folders
|
||||
WHERE user_id = :user_id AND parent_id IS NULL
|
||||
|
||||
UNION ALL
|
||||
|
||||
-- 递归查询:子文件夹
|
||||
SELECT f.id, f.name, f.parent_id, ft.depth + 1
|
||||
FROM folders f
|
||||
INNER JOIN folder_tree ft ON ft.id = f.parent_id
|
||||
WHERE f.user_id = :user_id
|
||||
)
|
||||
SELECT * FROM folder_tree ORDER BY depth, name;
|
||||
```
|
||||
|
||||
### Phase 3: 前端
|
||||
1. 创建 `FolderTree` 组件
|
||||
2. 改造 `KnowledgeView` 布局
|
||||
3. 实现文件夹右键菜单(重命名/删除)
|
||||
4. 实现新建文件夹弹窗
|
||||
5. 上传时强制选择文件夹
|
||||
|
||||
### Phase 4: 测试
|
||||
1. 文件夹 CRUD 测试
|
||||
2. 级联删除测试(删除文件夹 + 文档)
|
||||
3. 向量检索按文件夹过滤测试
|
||||
4. 前端交互测试
|
||||
|
||||
## 6. 技术约束
|
||||
|
||||
- SQLite 的递归 CTE 查询文件夹树
|
||||
- 删除文件夹时先删除子文件夹(递归),再删除文档
|
||||
- ChromaDB 的 `where` 过滤使用 `$starts_with` 做路径前缀匹配
|
||||
- 前端递归组件注意防止无限循环
|
||||
Reference in New Issue
Block a user