Add project documentation and specs

This commit is contained in:
2026-03-21 10:13:45 +08:00
parent e76f0828b9
commit 3a7f4174ab
20 changed files with 11179 additions and 0 deletions

View 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
```

View 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` 接口上传文件
- 创建 KGNodeentity_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
```

View 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:00APScheduler 清理 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:00APScheduler 定时任务),也可手动触发
- 数据来源:
1. **看板任务**:前一天创建的、状态 ≠ done 的任务,取前 20 条(按 created_at 倒序)
2. **对话记录**:前一天创建的对话,取其消息内容前 2000 字发给 LLM
- AI 处理流程:
1. 查询上述数据,拼装为分析文本
2. 发送给 LLMPrompt 要求输出 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

View File

@@ -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 关系抽取(实体之间的关系)
└── 存入 SQLitenodes + 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 助理系统的初始设计规格,将根据开发进展持续更新。*

View File

@@ -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 消耗统计

View 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. 注册表单验证正常 - 密码强度、格式校验有效

View 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等宽加粗
- 趋势图:高度 24px7个数据点
- 标签9pxletter-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. 数据刷新
- 页面进入时加载所有数据
- 支持手动刷新按钮(每个模块独立刷新)
- 数字变化时无动画(避免干扰)

View 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生成摘要 → 前端展示
```

View 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` 做路径前缀匹配
- 前端递归组件注意防止无限循环