feat(agents): Phase 8.4-10.5 built-in plugins, bundled skills, coordinator
This commit is contained in:
@@ -1,83 +0,0 @@
|
||||
# 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
|
||||
```
|
||||
@@ -1,192 +0,0 @@
|
||||
# 沟通系统增强设计
|
||||
|
||||
## 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
|
||||
```
|
||||
@@ -1,178 +0,0 @@
|
||||
# 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)
|
||||
@@ -1,602 +0,0 @@
|
||||
# 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 助理系统的初始设计规格,将根据开发进展持续更新。*
|
||||
@@ -1,57 +0,0 @@
|
||||
# Notes: Jarvis Knowledge Brain Blueprint
|
||||
|
||||
## Current-State Findings
|
||||
- Existing source domains already exist separately: conversations, documents, todos, tasks, forum posts.
|
||||
- Current long-term memory only comes from conversation extraction via `UserMemory`.
|
||||
- Current graph build path only uses indexed document chunks.
|
||||
- Scheduler infrastructure already exists and can host daily brain-learning jobs.
|
||||
- Frontend already exposes a `知识大脑` navigation entry, but it currently points to the graph page.
|
||||
|
||||
## Synthesized Findings
|
||||
|
||||
### What can be reused
|
||||
- `memory_service` as a seed for conversation extraction and recall.
|
||||
- `scheduler_service` as the base for daily learning workflows.
|
||||
- `tag_service` as an early foundation for brain tags.
|
||||
- Existing business tables as authoritative raw source records.
|
||||
|
||||
### What is missing
|
||||
- Unified event layer across all source systems.
|
||||
- Candidate memory layer between raw events and durable brain memory.
|
||||
- Timeline-aware memory model with reinforcement / archival states.
|
||||
- Retrieval path that combines long-term memory with recent relevant events.
|
||||
- Brain-specific APIs and a dedicated frontend dashboard module.
|
||||
|
||||
### Phase 1 objective
|
||||
- Build the minimum architecture needed for a real event-driven brain:
|
||||
- BrainEvent
|
||||
- BrainCandidate
|
||||
- BrainMemory
|
||||
- BrainTag and link tables
|
||||
- ingestion services
|
||||
- daily learning job
|
||||
- retrieval integration
|
||||
- brain dashboard APIs
|
||||
|
||||
## Additional Findings: Knowledge Parsing Normalization
|
||||
- Current document ingestion parses each format separately and builds chunks directly from ParsedNode items.
|
||||
- Current chunks already carry structural metadata, but there is no explicit parent-child chunk graph.
|
||||
- The agreed direction is to use MinerU for PDF only, keep existing parsers for DOCX/XLSX/CSV/MD/TXT, and converge all outputs into structured markdown.
|
||||
- normalized_content should be persisted on documents so preview, rebuild, and future chunking can reuse the same canonical text.
|
||||
- Lightweight hierarchy should be represented in chunk metadata first, not in a new relational tree schema.
|
||||
- Current DOCX upload failure in the running environment is caused by a missing python-docx installation in the active backend environment.
|
||||
|
||||
## Additional Findings: L3 Merge Progress
|
||||
- `backend/app/agents/state.py` has been expanded to the newer L3 runtime state shape so graph/runtime code can rely on structured continuity, tool-round, retry, routing-hop, and datetime-reference fields.
|
||||
- `backend/app/agents/graph.py` no longer contains merge markers and the phantom `EXECUTOR_ACCOUNTING` branch has been removed from graph registration and routing.
|
||||
- Accounting-style prompts are currently normalized onto `AgentRole.EXECUTOR` instead of a separate executor-accounting role, which avoids dangling enum/runtime references while keeping those intents routable.
|
||||
- `backend/tests/backend/app/agents/test_graph.py` has been reconciled onto the newer L3 runtime test branch and stale `EXECUTOR_ACCOUNTING` expectations were updated to `AgentRole.EXECUTOR`.
|
||||
- Tool execution now uses a shared async bridge in `backend/app/agents/tools/async_bridge.py`, and `search.py`, `schedule.py`, `task.py`, plus `forum.py` all route synchronous tool entrypoints through that same bridge to keep runtime behavior consistent inside and outside active event loops.
|
||||
- Current task/schedule canonicalization remains intentionally narrow for L3: task aliases (`content`, `date`, legacy priorities) and reminder aliases (`datetime`, `at`, `remind_at`, `time`, timezone variants) are normalized; deferred domains such as weather/accounting-specific tool routing remain outside this stabilization slice.
|
||||
- Targeted verification now covers async bridge behavior plus task/schedule alias persistence tests; local pytest invocation still depends on resolving environment-level startup issues when the interpreter exits before running the selected files.
|
||||
- L3 runtime/service integration now persists continuity snapshots in a single canonical envelope (`kind`, `version`, `state`) on both assistant message attachments and `Conversation.agent_state`, so streaming and sync chat entrypoints rehydrate the same shape.
|
||||
- The continuity rehydration path is also tolerant of older `Conversation` rows/models that do not expose `agent_state`, falling back to assistant message attachments instead of failing before graph execution.
|
||||
- The finalized L3 continuity contract persists a canonical `agent_continuity_state` snapshot: `turn_context.active_sub_commander`, `pending_action.type|owner_agent|owner_sub_commander|status`, `clarification_context.owning_agent|owning_sub_commander|target_action|question|status`, and `continuity_state.status|mode`.
|
||||
- `backend/app/services/agent_service.py` normalizes legacy persisted snapshots (`active_sub_flow`, `agent`, `sub_flow`, `action_type`, `awaiting_user_input`, `awaiting_clarification`) into that canonical shape on both save and rehydration so older brain-ingestion records still resume correctly.
|
||||
- Edge cases: explicit new requests may keep stale continuity in memory for override-aware routing, but only `continuity_state.status == fresh` participates in active continuation; clarification resumes use `continuity_state.mode = resume_after_clarification`.
|
||||
- `memory_service.build_memory_context(...)` remains the shared retrieval join point for conversation summaries, user memory, and BrainMemory recall, while `document_service` continues emitting BrainEvent records from upload flow without changing the graph runtime contract.
|
||||
@@ -1,427 +0,0 @@
|
||||
# Jarvis Knowledge Brain Phase 1 Blueprint
|
||||
|
||||
## 1. Phase 1 Goal
|
||||
Phase 1 establishes the first production-ready version of Jarvis's event-driven knowledge brain. The objective is not to finish the entire intelligence system, but to create the minimum architecture that lets Jarvis ingest key user actions from across the product, learn from them on a daily schedule, store only high-value knowledge, and retrieve that knowledge during future conversations.
|
||||
|
||||
Phase 1 should make the brain real in six ways:
|
||||
1. unify source events across core modules;
|
||||
2. create an intermediate candidate-learning layer;
|
||||
3. promote durable knowledge into long-term brain memory;
|
||||
4. maintain tags and time-aware traceability;
|
||||
5. expose APIs for inspection and management;
|
||||
6. allow the chat system to retrieve brain knowledge during answers.
|
||||
|
||||
---
|
||||
|
||||
## 2. Scope Boundaries
|
||||
|
||||
### In scope
|
||||
- New persistence models for brain events, candidates, memories, tags, and relationships.
|
||||
- Ingestion of source signals from conversations, knowledge documents, todos, kanban tasks, and forum posts.
|
||||
- A daily autonomous learning pipeline that tags, scores, deduplicates, and upgrades knowledge.
|
||||
- Retrieval integration for future responses.
|
||||
- Brain dashboard APIs.
|
||||
- A new frontend brain module structure replacing the current graph-only mental model.
|
||||
|
||||
### Out of scope for phase 1
|
||||
- Full graph-native reasoning engine.
|
||||
- Fully autonomous suggestion orchestration across all screens.
|
||||
- Complex reinforcement-learning style adaptation.
|
||||
- Fine-grained user-tunable learning policy UI.
|
||||
- Automatic deletion and archival heuristics beyond simple status transitions.
|
||||
|
||||
---
|
||||
|
||||
## 3. Target Architecture
|
||||
Phase 1 should introduce a four-layer brain pipeline:
|
||||
|
||||
1. **Source Records**
|
||||
Existing domain tables remain the source of truth: messages, documents/chunks, todos, tasks, forum posts/replies.
|
||||
|
||||
2. **BrainEvent**
|
||||
A normalized event layer representing meaningful user/system actions. This is the single intake format for downstream learning.
|
||||
|
||||
3. **BrainCandidate**
|
||||
AI-generated candidate knowledge distilled from one or more events. Candidates are scored, tagged, typed, and traced back to source events.
|
||||
|
||||
4. **BrainMemory**
|
||||
Durable long-term memory that Jarvis can retrieve during future interactions. This becomes the brain's core persistence layer.
|
||||
|
||||
Graph visualization should be treated as a **projection layer**, not the primary storage model. In later phases, graph nodes and edges can be generated from BrainMemory records and their relationships.
|
||||
|
||||
---
|
||||
|
||||
## 4. Data Model Additions
|
||||
|
||||
### 4.1 BrainEvent
|
||||
Purpose: normalized raw learning input.
|
||||
|
||||
Recommended fields:
|
||||
- `id`
|
||||
- `user_id`
|
||||
- `source_type` (`conversation`, `document`, `todo`, `task`, `forum_post`, `forum_reply`)
|
||||
- `source_id`
|
||||
- `event_type` (`created`, `updated`, `completed`, `mentioned`, `uploaded`, `resolved`, `marked_important`, etc.)
|
||||
- `occurred_at`
|
||||
- `event_date`
|
||||
- `title`
|
||||
- `content_summary`
|
||||
- `raw_excerpt`
|
||||
- `metadata_` (JSON; source-specific facts such as conversation_id, task status, folder path)
|
||||
- `importance_signal` (numeric seed score)
|
||||
- `is_user_pinned`
|
||||
- `processed_at`
|
||||
- `status` (`pending`, `processed`, `ignored`)
|
||||
|
||||
Indexes:
|
||||
- `(user_id, event_date)`
|
||||
- `(user_id, source_type, source_id)`
|
||||
- `(user_id, status, occurred_at)`
|
||||
|
||||
### 4.2 BrainCandidate
|
||||
Purpose: intermediate learned knowledge awaiting acceptance into durable memory.
|
||||
|
||||
Recommended fields:
|
||||
- `id`
|
||||
- `user_id`
|
||||
- `candidate_type` (`preference`, `habit`, `project_fact`, `decision`, `solution`, `topic`, `goal`, `temporary_focus`)
|
||||
- `title`
|
||||
- `summary`
|
||||
- `importance_score`
|
||||
- `confidence_score`
|
||||
- `time_scope` (`short_term`, `phase`, `long_term`)
|
||||
- `valid_from`
|
||||
- `valid_to`
|
||||
- `source_event_ids` (JSON array)
|
||||
- `reasoning_trace` (short explanation of why the system extracted it)
|
||||
- `status` (`new`, `promoted`, `rejected`, `merged`)
|
||||
- `created_at`
|
||||
- `reviewed_at`
|
||||
|
||||
### 4.3 BrainMemory
|
||||
Purpose: durable brain knowledge used at retrieval time.
|
||||
|
||||
Recommended fields:
|
||||
- `id`
|
||||
- `user_id`
|
||||
- `memory_type` (`preference`, `habit`, `goal`, `project_fact`, `decision`, `solution`, `topic_profile`)
|
||||
- `title`
|
||||
- `content`
|
||||
- `importance`
|
||||
- `confidence`
|
||||
- `timeline_date`
|
||||
- `first_learned_at`
|
||||
- `last_reinforced_at`
|
||||
- `reinforcement_count`
|
||||
- `status` (`active`, `archived`, `deleted`)
|
||||
- `origin_candidate_id`
|
||||
- `origin_source_types` (JSON array)
|
||||
- `metadata_` (JSON)
|
||||
|
||||
### 4.4 BrainTag
|
||||
Purpose: independent tagging layer for brain browsing, filtering, and scoring.
|
||||
|
||||
Recommended fields:
|
||||
- `id`
|
||||
- `user_id`
|
||||
- `name`
|
||||
- `category` (`topic`, `value`, `time`, `source`)
|
||||
- `priority` (`important`, `secondary`)
|
||||
- `score`
|
||||
- `last_seen_at`
|
||||
- `created_at`
|
||||
|
||||
### 4.5 Link Tables
|
||||
Add many-to-many link tables:
|
||||
- `brain_event_tags`
|
||||
- `brain_candidate_tags`
|
||||
- `brain_memory_tags`
|
||||
- optional `brain_memory_events` for direct memory-to-event traceability beyond JSON arrays
|
||||
|
||||
These link tables are critical because phase 1 needs tag filters and timeline tracing before advanced graph projection exists.
|
||||
|
||||
---
|
||||
|
||||
## 5. Ingestion Strategy
|
||||
Phase 1 should not rewrite existing modules. Instead, it should add thin ingestion hooks near existing write paths.
|
||||
|
||||
### Conversation ingestion
|
||||
Trigger points:
|
||||
- after user message creation
|
||||
- after assistant completion
|
||||
- after memory extraction / summary creation
|
||||
|
||||
Event examples:
|
||||
- important user instruction
|
||||
- explicit “remember this” request
|
||||
- repeated topic cluster
|
||||
- conversation-derived decision or unresolved goal
|
||||
|
||||
### Document ingestion
|
||||
Trigger points:
|
||||
- after upload success
|
||||
- after indexing completes
|
||||
- after manual chunk edits
|
||||
|
||||
Event examples:
|
||||
- document uploaded
|
||||
- document indexed
|
||||
- high-value section discovered
|
||||
- document summary available
|
||||
|
||||
### Todo ingestion
|
||||
Trigger points:
|
||||
- todo created
|
||||
- todo completed
|
||||
- AI-generated todo created
|
||||
|
||||
Event examples:
|
||||
- planned work item
|
||||
- recurring operational duty
|
||||
- completion signal reflecting actual user focus
|
||||
|
||||
### Task/Kanban ingestion
|
||||
Trigger points:
|
||||
- task created
|
||||
- task status changed
|
||||
- task completed
|
||||
- priority changed
|
||||
|
||||
Event examples:
|
||||
- declared project goal
|
||||
- active workstream
|
||||
- resolved milestone
|
||||
|
||||
### Forum ingestion
|
||||
Trigger points:
|
||||
- post created
|
||||
- reply created
|
||||
- forum instruction executed or referenced
|
||||
|
||||
Event examples:
|
||||
- public project decision
|
||||
- repeated operational issue
|
||||
- reusable explanation or solution
|
||||
|
||||
Implementation note: source ingestion should create BrainEvent rows synchronously or via lightweight background tasks, but should not block the original user flow.
|
||||
|
||||
---
|
||||
|
||||
## 6. Learning and Promotion Pipeline
|
||||
Phase 1 should add a new daily scheduler workflow dedicated to the brain.
|
||||
|
||||
### New scheduler job: `brain_daily_learning_task`
|
||||
Suggested run: once daily after the bulk of user activity, for example 01:00 or configurable per user later.
|
||||
|
||||
Pipeline steps:
|
||||
1. collect unprocessed `BrainEvent` rows for the target date;
|
||||
2. cluster by source, topic, and repeated patterns;
|
||||
3. ask the LLM to produce candidate knowledge with tags and importance explanations;
|
||||
4. deduplicate against existing `BrainMemory` by semantic and rule-based matching;
|
||||
5. promote high-confidence candidates into `BrainMemory`;
|
||||
6. mark low-value candidates rejected or retained as observation-only;
|
||||
7. refresh tag scores and priority levels;
|
||||
8. mark consumed events as processed.
|
||||
|
||||
### Promotion rules for phase 1
|
||||
Promote automatically when any of these are true:
|
||||
- user explicitly requested the system to remember something;
|
||||
- the same topic appears across multiple sources;
|
||||
- a solution/decision was formed and looks reusable;
|
||||
- a stable preference or habit is seen repeatedly;
|
||||
- a task/todo/forum thread confirms relevance with user action.
|
||||
|
||||
Keep as candidate-only when:
|
||||
- information is recent but not yet stable;
|
||||
- importance is uncertain;
|
||||
- it appears only once without reinforcement.
|
||||
|
||||
Reject when:
|
||||
- content is obviously transient;
|
||||
- it is too generic to help future answers;
|
||||
- it duplicates active memory without adding new value.
|
||||
|
||||
---
|
||||
|
||||
## 7. Retrieval Integration
|
||||
Phase 1 must let chat use the brain in a controlled way.
|
||||
|
||||
### New retrieval service
|
||||
Add a dedicated `brain_retrieval_service` or extend `memory_service` with brain-aware retrieval APIs.
|
||||
|
||||
Responsibilities:
|
||||
- retrieve top relevant `BrainMemory` rows by query, tags, time context, and importance;
|
||||
- optionally retrieve recent `BrainEvent` summaries for recency-sensitive answers;
|
||||
- merge existing `UserMemory` and `MemorySummary` into one retrieval result shape;
|
||||
- support limits to avoid prompt bloat.
|
||||
|
||||
### Retrieval policy
|
||||
At answer time:
|
||||
- always consider long-term `BrainMemory`;
|
||||
- include recent event summaries only when the question appears time-sensitive or project-state-sensitive;
|
||||
- cap injected brain context to a small curated set.
|
||||
|
||||
Recommended first integration path:
|
||||
- extend `build_memory_context()` to append a new `【知识大脑】` block built from `BrainMemory` retrieval.
|
||||
- keep existing conversation summary logic intact.
|
||||
|
||||
This gives immediate product value without requiring a full prompt orchestration rewrite.
|
||||
|
||||
---
|
||||
|
||||
## 8. Backend Services to Add or Refactor
|
||||
|
||||
### New services
|
||||
1. `brain_event_service.py`
|
||||
- normalize incoming source data into BrainEvent rows
|
||||
- provide source-specific helper constructors
|
||||
|
||||
2. `brain_learning_service.py`
|
||||
- run daily candidate extraction
|
||||
- score, dedupe, and promote memories
|
||||
|
||||
3. `brain_tag_service.py`
|
||||
- manage tags, scoring, priority updates, and cleanup suggestions
|
||||
|
||||
4. `brain_retrieval_service.py`
|
||||
- retrieve relevant memories and recent events for chat and UI
|
||||
|
||||
### Existing services to extend
|
||||
- `memory_service.py`: integrate BrainMemory retrieval and possibly migrate `UserMemory` into the new model later
|
||||
- `scheduler_service.py`: register brain daily learning job
|
||||
- `agent_service.py`: inject retrieved brain context into chat pipeline
|
||||
- `document_service.py`, `todo_service.py`, task/forum write paths: emit BrainEvent rows
|
||||
|
||||
---
|
||||
|
||||
## 9. API Plan
|
||||
Phase 1 should add a dedicated `/api/brain` router.
|
||||
|
||||
### Read APIs
|
||||
- `GET /api/brain/overview`
|
||||
- counts: active memories, candidates, important tags, recent events
|
||||
- today's learning summary
|
||||
|
||||
- `GET /api/brain/memories`
|
||||
- filters: tag, type, status, date range, source type
|
||||
|
||||
- `GET /api/brain/candidates`
|
||||
- filters: status, date, score threshold
|
||||
|
||||
- `GET /api/brain/tags`
|
||||
- segmented into important and secondary
|
||||
|
||||
- `GET /api/brain/timeline`
|
||||
- grouped by day/week; includes events, candidate promotions, reinforced memories
|
||||
|
||||
- `GET /api/brain/memory/{id}`
|
||||
- full traceability including linked events and tags
|
||||
|
||||
### Write/management APIs
|
||||
- `POST /api/brain/memory/{id}/promote`
|
||||
- `POST /api/brain/memory/{id}/archive`
|
||||
- `DELETE /api/brain/memory/{id}`
|
||||
- `POST /api/brain/tag/{id}/promote`
|
||||
- `POST /api/brain/tag/{id}/demote`
|
||||
- `DELETE /api/brain/tag/{id}`
|
||||
- `POST /api/brain/learn/run`
|
||||
- manual trigger for daily learning pipeline
|
||||
|
||||
### Compatibility note
|
||||
Do not remove `/api/graph` in phase 1. Keep it as a legacy projection route while the new brain module is introduced.
|
||||
|
||||
---
|
||||
|
||||
## 10. Frontend Module Structure
|
||||
The current `知识大脑` nav item should stop meaning “graph only” and become a real brain dashboard.
|
||||
|
||||
### Route strategy
|
||||
Preferred phase 1 structure:
|
||||
- `/brain` → new knowledge brain dashboard
|
||||
- `/graph` → graph view tab or subview under the brain module, retained for relation visualization
|
||||
|
||||
### Brain dashboard sections
|
||||
1. **Overview header**
|
||||
- total active memories
|
||||
- today's learned items
|
||||
- important tags count
|
||||
- last learning run
|
||||
|
||||
2. **Important tags panel**
|
||||
- AI-ranked important tags
|
||||
- click to filter related memories and timeline entries
|
||||
|
||||
3. **Secondary tags panel**
|
||||
- lower-priority tags with cleanup actions
|
||||
|
||||
4. **Recent learned knowledge**
|
||||
- newly promoted memories
|
||||
- reasons and source badges
|
||||
|
||||
5. **Timeline panel**
|
||||
- daily grouped events and promotions
|
||||
- support time-based backtracking
|
||||
|
||||
6. **Graph subview**
|
||||
- optional tab or secondary panel for relation projection
|
||||
|
||||
### User actions in phase 1
|
||||
- delete memory
|
||||
- archive memory
|
||||
- promote/demote tag priority
|
||||
- manually trigger learning run
|
||||
- inspect why a memory exists
|
||||
|
||||
This is enough to make the brain visible and manageable even before advanced graph reasoning exists.
|
||||
|
||||
---
|
||||
|
||||
## 11. Suggested Delivery Breakdown
|
||||
|
||||
### Step 1: Persistence foundation
|
||||
- add brain models and migrations
|
||||
- add SQLAlchemy registrations and schemas
|
||||
|
||||
### Step 2: Event ingestion
|
||||
- emit BrainEvent rows from conversation/document/todo/task/forum flows
|
||||
|
||||
### Step 3: Learning workflow
|
||||
- implement daily learning job and manual trigger API
|
||||
|
||||
### Step 4: Retrieval integration
|
||||
- wire BrainMemory into chat context assembly
|
||||
|
||||
### Step 5: Brain dashboard backend
|
||||
- add overview, memories, tags, timeline endpoints
|
||||
|
||||
### Step 6: Brain dashboard frontend
|
||||
- add `/brain` page and move graph into a subview or separate tab
|
||||
|
||||
---
|
||||
|
||||
## 12. Risks and Guardrails
|
||||
|
||||
### Main risks
|
||||
- over-collection leading to noisy memories;
|
||||
- prompt bloat from injecting too much brain context;
|
||||
- duplicate memory creation across repeated daily runs;
|
||||
- unclear distinction between candidate and durable memory;
|
||||
- UI becoming graph-centric again instead of brain-centric.
|
||||
|
||||
### Guardrails
|
||||
- enforce candidate layer before promotion;
|
||||
- cap retrieval size strictly;
|
||||
- keep source traceability for every promoted memory;
|
||||
- make tag cleanup explicit in UI;
|
||||
- treat graph as a projection, not the source of truth.
|
||||
|
||||
---
|
||||
|
||||
## 13. Phase 1 Success Criteria
|
||||
Phase 1 is successful when all of the following are true:
|
||||
- the system creates normalized BrainEvent rows from all five major source domains;
|
||||
- a scheduled daily learning job produces candidates and promotes high-value memories;
|
||||
- Jarvis can retrieve durable brain memories during future answers;
|
||||
- the frontend exposes a real brain dashboard with tags, recent knowledge, and timeline;
|
||||
- users can inspect and clean what the system learned;
|
||||
- the old graph page is no longer the only visible representation of the brain.
|
||||
@@ -1,141 +0,0 @@
|
||||
# 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 消耗统计
|
||||
@@ -1,249 +0,0 @@
|
||||
# 注册界面 + 设置界面 功能设计
|
||||
|
||||
## 概述
|
||||
|
||||
为 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. 注册表单验证正常 - 密码强度、格式校验有效
|
||||
@@ -1,267 +0,0 @@
|
||||
# 数据统计页面重新设计
|
||||
|
||||
## 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. 数据刷新
|
||||
|
||||
- 页面进入时加载所有数据
|
||||
- 支持手动刷新按钮(每个模块独立刷新)
|
||||
- 数字变化时无动画(避免干扰)
|
||||
@@ -1,473 +0,0 @@
|
||||
# 交互广场重新设计
|
||||
|
||||
## 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生成摘要 → 前端展示
|
||||
```
|
||||
@@ -1,307 +0,0 @@
|
||||
# 知识库文件夹分层设计
|
||||
|
||||
> **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` 做路径前缀匹配
|
||||
- 前端递归组件注意防止无限循环
|
||||
@@ -1,157 +0,0 @@
|
||||
# LLM 模型配置表格设计
|
||||
|
||||
## 1. 概述
|
||||
|
||||
重新设计 Settings 页面的 LLM 模型配置 UI,将原有的卡片列表改为表格行内编辑形式,简化交互、减少页面长度,同时支持多模型配置。
|
||||
|
||||
## 2. 需求
|
||||
|
||||
- **chat**: 必填,多个(子智能体可选不同模型)
|
||||
- **vlm**: 选填,多个
|
||||
- **embedding**: 必填,1 个(知识库专用)
|
||||
- **rerank**: 必填,1 个(知识库专用)
|
||||
|
||||
## 3. UI 设计
|
||||
|
||||
### 3.1 整体布局
|
||||
|
||||
每种 LLM 类型(chat/vlm/embedding/rerank)独立成区,区头部显示类型名称和必填/选填标识,右上角有 [+] 添加按钮。
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ // LLM CONFIGURATION │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ ┌─ CHAT ─────────────────────────────────────────────── [+] │
|
||||
│ │ 名称 │ Provider │ 模型 │ 状态 │ 操作 │
|
||||
│ ├─────────────────────────────────────────────────────────┤ │
|
||||
│ │ Agent-Chat │ OpenAI │ gpt-4o │ ● 可用 │ ▶ ✕ │
|
||||
│ └─────────────────────────────────────────────────────────┘ │
|
||||
│ ... (vlm, embedding, rerank 同理) │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 3.2 表格列(精简版)
|
||||
|
||||
| 列 | 说明 |
|
||||
|----|------|
|
||||
| 名称 | 模型名称,支持输入编辑 |
|
||||
| Provider | 下拉选择:OpenAI / Claude / Ollama / DeepSeek / Custom |
|
||||
| 模型 | 模型名称,支持输入编辑 |
|
||||
| 状态 | ● 可用(绿色)/ ○ 不可用(灰色)/ ⚠ 必填未填(红色) |
|
||||
| 操作 | 展开详情按钮 ▶ / 删除按钮 ✕ |
|
||||
|
||||
### 3.3 行内展开详情面板
|
||||
|
||||
点击任意行,行下方展开详情表单:
|
||||
|
||||
```
|
||||
│ ▼ Agent-Chat │ OpenAI │ gpt-4o │ ● 可用 │ ▶ ✕ │
|
||||
│ ┌─────────────────────────────────────────────────────────┐ │
|
||||
│ │ │ │
|
||||
│ │ Provider: [OpenAI ▼] Model: [gpt-4o ] │ │
|
||||
│ │ Base URL: [https://api.openai.com/v1 ] │ │
|
||||
│ │ API Key: [sk-•••••••••••••••• ] 👁 │ │
|
||||
│ │ │ │
|
||||
│ │ [▶ 测试连接] [保存] [取消] │ │
|
||||
│ └─────────────────────────────────────────────────────────┘ │
|
||||
```
|
||||
|
||||
### 3.4 状态说明
|
||||
|
||||
| 状态 | 颜色 | 含义 |
|
||||
|------|------|------|
|
||||
| ● 可用 | 绿色 | 测试通过 |
|
||||
| ○ 不可用 | 灰色 | 未测试或测试失败 |
|
||||
| ⚠ 必填未填 | 红色 | chat/embedding/rerank 未配置 |
|
||||
|
||||
### 3.5 警告提示
|
||||
|
||||
当 chat/embedding/rerank 任一类型为空时,表格顶部显示红色警告条:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ ⚠ chat / embedding / rerank 为知识库必填,请确保已配置 │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 4. 交互规则
|
||||
|
||||
| 动作 | 行为 |
|
||||
|------|------|
|
||||
| 添加模型 | 点击 [+] 在对应类型底部添加新行,状态默认为 ○ 不可用 |
|
||||
| 展开编辑 | 点击任意行,行内展开详情面板,同时收起其他已展开的行 |
|
||||
| 测试连接 | 点击"测试连接",调用后端 API,测试通过则状态变 ● 可用,失败显示错误 Toast |
|
||||
| 保存 | 只有测试通过的模型才能保存,保存后更新 originalLlmConfig |
|
||||
| 删除 | 点击 ✕ 删除该模型(embedding/rerank 至少保留 1 个) |
|
||||
| 取消编辑 | 点击"取消"或再次点击展开按钮,收起详情面板,表单数据恢复原值 |
|
||||
| Provider 变化 | 自动填充对应 Provider 的默认 Base URL |
|
||||
|
||||
## 5. 数据模型
|
||||
|
||||
```typescript
|
||||
interface LLMModelConfig {
|
||||
name: string // 模型名称
|
||||
provider: 'openai' | 'claude' | 'ollama' | 'deepseek' | 'custom'
|
||||
model: string // 模型名称
|
||||
base_url: string // API Base URL
|
||||
api_key: string // API Key
|
||||
enabled: boolean // 是否启用
|
||||
}
|
||||
|
||||
interface LLMConfig {
|
||||
chat: LLMModelConfig[] // 必填,多个
|
||||
vlm: LLMModelConfig[] // 选填,多个
|
||||
embedding: LLMModelConfig[] // 必填,1个
|
||||
rerank: LLMModelConfig[] // 必填,1个
|
||||
}
|
||||
```
|
||||
|
||||
## 6. 后端 API
|
||||
|
||||
### 6.1 保存策略
|
||||
|
||||
`saveModel(type, index)` 发送完整 `LLMConfig` 对象到后端,后端整体替换该类型的模型列表。
|
||||
|
||||
- chat/vlm: 列表直接替换
|
||||
- embedding/rerank: 列表直接替换(限制最多 1 个)
|
||||
|
||||
### 6.2 测试连接 API
|
||||
|
||||
```typescript
|
||||
POST /api/settings/llm/test
|
||||
{
|
||||
"type": "chat" | "vlm" | "embedding" | "rerank",
|
||||
"provider": "openai" | "claude" | "ollama" | "deepseek" | "custom",
|
||||
"model": "gpt-4o",
|
||||
"base_url": "https://api.openai.com/v1",
|
||||
"api_key": "sk-..."
|
||||
}
|
||||
```
|
||||
|
||||
返回:
|
||||
```typescript
|
||||
{ "success": true, "message": "连接成功" }
|
||||
{ "success": false, "error": "错误信息" }
|
||||
```
|
||||
|
||||
## 7. 组件结构
|
||||
|
||||
```
|
||||
SettingsView.vue
|
||||
├── LLMConfigSection (chat/vlm/embedding/rerank 四区)
|
||||
│ ├── LLMTypeCard (每个类型一个卡片)
|
||||
│ │ ├── LLMTable (表格头部 + 列表)
|
||||
│ │ │ ├── LLMTableRow (每行模型)
|
||||
│ │ │ └── LLMExpandPanel (展开的详情面板)
|
||||
│ │ └── LLMEmptyState (空状态 + 添加按钮)
|
||||
│ └── LLMWarning (必填警告条)
|
||||
```
|
||||
|
||||
## 8. 实现要点
|
||||
|
||||
1. **单行展开**: 点击行时收起其他已展开行,保持 UI 简洁
|
||||
2. **测试通过才可保存**: 保存按钮仅在 `model.enabled === true` 时可用
|
||||
3. **API Key 脱敏**: 列表中不显示 API Key,详情面板中默认隐藏(显示为 ••••)
|
||||
4. **Provider 默认 URL**: `onProviderChange` 自动填充默认值
|
||||
5. **深拷贝比较**: `isModelDirty` 使用 `JSON.stringify` 深拷贝比较
|
||||
6. **originalLlmConfig 同步**: 每次保存成功后更新原始配置副本
|
||||
@@ -1,288 +0,0 @@
|
||||
# Skill 系统设计方案
|
||||
|
||||
## 1. 概述
|
||||
|
||||
### 1.1 背景
|
||||
|
||||
当前 Jarvis 系统采用基于 LangGraph 的多 Agent 架构(Master/Planner/Executor/Librarian/Analyst),通过关键词规则路由到子 Agent。系统缺乏可扩展的 Skill 机制,无法让 Agent 按需调用自定义能力。
|
||||
|
||||
### 1.2 目标
|
||||
|
||||
构建一个 **Skill 系统**,让每个 Agent 能够:
|
||||
- 挂载可配置的 Skill 能力插件
|
||||
- 由 LLM 自主判断何时使用哪个 Skill
|
||||
- 支持私有/团队共享/市场三种可见性
|
||||
- Skill 作为 Agent 的指令模板 + 工具组合
|
||||
|
||||
---
|
||||
|
||||
## 2. 核心理念
|
||||
|
||||
**Skill 是 Agent 的"能力插件",由 LLM 自主决策调用时机。**
|
||||
|
||||
```
|
||||
用户: "帮我规划今天的工作"
|
||||
│
|
||||
▼
|
||||
Master Agent 理解意图
|
||||
│
|
||||
▼
|
||||
路由到 Planner Agent
|
||||
│
|
||||
▼
|
||||
Planner 分析任务 → 自主判断需要什么 Skill
|
||||
│
|
||||
├──→ 需要数据 → 调用 "数据获取" Skill
|
||||
├──→ 需要优先级 → 调用 "任务排序" Skill
|
||||
└──→ 需要时间安排 → 调用 "日程规划" Skill
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 数据模型
|
||||
|
||||
### 3.1 Skill 实体
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|-----|------|-----|
|
||||
| id | UUID | 主键 |
|
||||
| name | str | Skill 名称,如 "任务排序" |
|
||||
| description | str | 供 LLM 理解该 Skill 的用途 |
|
||||
| instructions | str | Agent 执行时的系统指令模板 |
|
||||
| agent_type | AgentRole | 适用于哪个 Agent (master/planner/executor/librarian/analyst) |
|
||||
| tools | List[str] | 引用的工具名称列表 |
|
||||
| required_context | List[str] | 需要的前置数据 |
|
||||
| output_format | str | 输出格式要求(可选) |
|
||||
| visibility | enum | private/team/market |
|
||||
| team_id | UUID | 团队 ID(visibility=team 时使用) |
|
||||
| is_active | bool | 是否启用 |
|
||||
| owner_id | UUID | 创建者 ID |
|
||||
| created_at | datetime | 创建时间 |
|
||||
| updated_at | datetime | 更新时间 |
|
||||
|
||||
### 3.2 Agent-Skill 关联
|
||||
|
||||
每个 Agent 运行时从数据库加载其 `agent_type` 对应的所有 `is_active=True` 的 Skills,作为可选能力供 LLM 调用。
|
||||
|
||||
---
|
||||
|
||||
## 4. 系统架构
|
||||
|
||||
### 4.1 组件关系
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
│ Agent Brain │
|
||||
│ ┌─────────────────────────────────────────────┐ │
|
||||
│ │ Master Agent (理解意图,路由到子 Agent) │ │
|
||||
│ └─────────────────────────────────────────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌─────────────────────────────────────────────┐ │
|
||||
│ │ [Planner] [Executor] [Librarian] ... │ │
|
||||
│ │ │ │ │ │ │
|
||||
│ │ └───────────┼────────────┘ │ │
|
||||
│ │ ▼ │ │
|
||||
│ │ ┌──────────────────┐ │ │
|
||||
│ │ │ Skill Registry │ │ │
|
||||
│ │ │ (可用的 Skills) │ │ │
|
||||
│ │ └────────┬─────────┘ │ │
|
||||
│ │ │ │ │
|
||||
│ │ LLM 自主判断使用哪个 Skill │ │
|
||||
│ └─────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 4.2 组件说明
|
||||
|
||||
| 组件 | 职责 |
|
||||
|-----|------|
|
||||
| Skill Registry | 存储 Skill 定义,提供加载接口,权限校验 |
|
||||
| Skill Loader | 运行时加载 Agent 对应的 Skills |
|
||||
| Skill Executor | 执行 Skill 指令,调用工具链 |
|
||||
|
||||
---
|
||||
|
||||
## 5. Skill 定义示例
|
||||
|
||||
### 5.1 任务排序 Skill
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "任务排序",
|
||||
"description": "根据优先级、截止日期、依赖关系对任务列表进行智能排序",
|
||||
"instructions": "你是一个任务排序专家。接收任务列表后,按以下规则排序:\n1. 紧急且重要优先\n2. 有截止日期的优先\n3. 依赖其他任务的优先\n输出排序后的任务列表及理由。",
|
||||
"agent_type": "planner",
|
||||
"tools": ["get_tasks"],
|
||||
"required_context": ["原始任务列表"]
|
||||
}
|
||||
```
|
||||
|
||||
### 5.2 知识检索 Skill
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "知识检索",
|
||||
"description": "从用户知识库中检索相关内容,支持向量检索和关键词检索",
|
||||
"instructions": "你是一个知识管理员。从知识库中检索与用户问题相关的内容,返回相关文档片段和来源。",
|
||||
"agent_type": "librarian",
|
||||
"tools": ["search_knowledge", "hybrid_search"],
|
||||
"required_context": ["用户查询"]
|
||||
}
|
||||
```
|
||||
|
||||
### 5.3 数据分析 Skill
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "效率分析",
|
||||
"description": "分析任务完成情况,计算工作效率指标",
|
||||
"instructions": "你是一个数据分析师。接收任务列表后,分析:\n1. 完成率\n2. 平均完成时间\n3. 阻塞原因\n4. 改进建议",
|
||||
"agent_type": "analyst",
|
||||
"tools": ["get_tasks", "get_stats"],
|
||||
"required_context": ["任务数据"]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. API 设计
|
||||
|
||||
### 6.1 Skill 管理
|
||||
|
||||
| 方法 | 路径 | 说明 |
|
||||
|-----|------|-----|
|
||||
| POST | /api/skills | 创建 Skill |
|
||||
| GET | /api/skills | 列表(支持过滤 agent_type, visibility) |
|
||||
| GET | /api/skills/{id} | 详情 |
|
||||
| PUT | /api/skills/{id} | 更新 |
|
||||
| DELETE | /api/skills/{id} | 删除 |
|
||||
|
||||
### 6.2 Skill 执行
|
||||
|
||||
| 方法 | 路径 | 说明 |
|
||||
|-----|------|-----|
|
||||
| POST | /api/skills/{id}/execute | 手动执行 Skill |
|
||||
| GET | /api/skills/execute/{execution_id} | 查询执行结果 |
|
||||
|
||||
---
|
||||
|
||||
## 7. 数据库表设计
|
||||
|
||||
### 7.1 skill 表
|
||||
|
||||
```sql
|
||||
CREATE TABLE skill (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name VARCHAR(100) NOT NULL,
|
||||
description TEXT,
|
||||
instructions TEXT NOT NULL,
|
||||
agent_type VARCHAR(50) NOT NULL,
|
||||
tools JSONB DEFAULT '[]',
|
||||
required_context JSONB DEFAULT '[]',
|
||||
output_format TEXT,
|
||||
visibility VARCHAR(20) DEFAULT 'private',
|
||||
team_id UUID,
|
||||
is_active BOOLEAN DEFAULT true,
|
||||
owner_id UUID NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_skill_agent_type ON skill(agent_type);
|
||||
CREATE INDEX idx_skill_visibility ON skill(visibility);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. 前端界面
|
||||
|
||||
### 8.1 Skill 管理入口
|
||||
|
||||
入口位置:智能链路 → Skill 市场
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ 智能链路 → Skill 市场 │
|
||||
├─────────────────────────────────────────────┤
|
||||
│ [我的 Skills] [团队共享] [市场] │
|
||||
├─────────────────────────────────────────────┤
|
||||
│ ┌───────────────────────────────────────┐ │
|
||||
│ │ 任务排序 │ │
|
||||
│ │ 适用: Planner Agent │ │
|
||||
│ │ 工具: get_tasks │ │
|
||||
│ │ 描述: 根据优先级排序任务列表 │ │
|
||||
│ │ 可见: 私有 │ │
|
||||
│ │ [编辑] [禁用] [复制] │ │
|
||||
│ └───────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 8.2 Skill 编辑界面
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ 创建/编辑 Skill │
|
||||
├─────────────────────────────────────────────┤
|
||||
│ 名称: [________________] │
|
||||
│ 描述: [________________] │
|
||||
│ │
|
||||
│ 适用 Agent: │
|
||||
│ ( ) Master (●) Planner ( ) Executor │
|
||||
│ ( ) Librarian ( ) Analyst │
|
||||
│ │
|
||||
│ 引用工具: │
|
||||
│ ☑ get_tasks ☑ create_task │
|
||||
│ ☐ search_knowledge ☐ hybrid_search │
|
||||
│ │
|
||||
│ 指令模板: │
|
||||
│ ┌─────────────────────────────────────┐ │
|
||||
│ │ 你是一个任务排序专家... │ │
|
||||
│ └─────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ 可见性: │
|
||||
│ (●) 私有 ( ) 团队共享 ( ) 公开市场 │
|
||||
│ │
|
||||
│ [取消] [保存] │
|
||||
└─────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. 与现有系统集成
|
||||
|
||||
| 现有组件 | 集成方式 |
|
||||
|---------|---------|
|
||||
| Agent Role | Skill.agent_type 引用现有 AgentRole 枚举 |
|
||||
| Tools | Skill.tools 引用现有 ALL_TOOLS 中的工具名 |
|
||||
| Prompts | Skill.instructions 作为 Agent 系统提示的补充 |
|
||||
| User/Team | 复用现有权限体系,visibility 字段控制 |
|
||||
| Router | Master Agent 路由逻辑不变,Skill 由子 Agent 按需调用 |
|
||||
|
||||
---
|
||||
|
||||
## 10. 实现计划
|
||||
|
||||
### Phase 1: 基础框架
|
||||
- [ ] Skill 数据模型与 CRUD API
|
||||
- [ ] Skill Registry 服务
|
||||
- [ ] Skill 加载机制(Agent 初始化时注入)
|
||||
- [ ] 前端 Skill 管理界面
|
||||
|
||||
### Phase 2: 执行机制
|
||||
- [ ] Skill Executor
|
||||
- [ ] 工具调用桥接
|
||||
- [ ] 执行结果返回
|
||||
|
||||
### Phase 3: 高级特性
|
||||
- [ ] 团队共享机制
|
||||
- [ ] Skill 市场
|
||||
- [ ] Skill 编排(多个 Skill 串联)
|
||||
|
||||
---
|
||||
|
||||
## 11. 风险与约束
|
||||
|
||||
1. **LLM 自主性**:依赖 LLM 准确理解 Skill 描述,需优化 prompt
|
||||
2. **工具兼容性**:Skill 引用的工具需在 ALL_TOOLS 中存在
|
||||
3. **权限控制**:团队共享需防止越权访问
|
||||
@@ -1,561 +0,0 @@
|
||||
# Schedule Planner Agent Redesign
|
||||
|
||||
## Goal
|
||||
|
||||
Replace the current planner role with a schedule-focused planning system that analyzes conversation history, the task board, and forum signals to produce actionable scheduling recommendations for the user.
|
||||
|
||||
## Scope
|
||||
|
||||
This redesign covers both the main planner role and its subagents across backend orchestration, prompts, routing, scheduled execution, todo generation, frontend presentation, and related tests.
|
||||
|
||||
## User-Approved Direction
|
||||
|
||||
- Replace the current path-planning semantics with schedule-planning semantics.
|
||||
- Redesign both the main planner role and its subagents.
|
||||
- Inputs for planning:
|
||||
- conversation history
|
||||
- task board
|
||||
- forum information
|
||||
- Output style:
|
||||
- conclusion first
|
||||
- executable schedule next
|
||||
- Trigger modes:
|
||||
- when the user explicitly asks for scheduling advice
|
||||
- at a fixed daily time
|
||||
- Daily scheduled analysis should write actionable suggestions into todo items.
|
||||
|
||||
## Architecture
|
||||
|
||||
### Main Role
|
||||
|
||||
The current `planner` role will be replaced at the system level by a new role id:
|
||||
|
||||
- `schedule_planner`
|
||||
|
||||
Its responsibility is no longer “find the shortest execution path for a goal.” Instead, it becomes the scheduling brain that:
|
||||
|
||||
1. understands current commitments and pressure signals
|
||||
2. evaluates urgency, importance, dependency, and timing
|
||||
3. recommends near-term scheduling actions
|
||||
4. converts useful scheduled guidance into concrete todo items when triggered by the daily scheduler
|
||||
|
||||
### Subagents
|
||||
|
||||
The existing planner subagent structure will be redesigned into two schedule-specific subagents:
|
||||
|
||||
- `schedule_analysis`
|
||||
- analyzes conversation history, task board state, and forum signals
|
||||
- identifies priorities, pressure points, conflicts, dependencies, risks, and things that can be delayed
|
||||
|
||||
- `schedule_planning`
|
||||
- converts analysis into an execution-oriented schedule recommendation
|
||||
- outputs conclusion first, then a practical schedule proposal
|
||||
- when running from the daily scheduled workflow, produces todo-ready action items
|
||||
|
||||
### Trigger Paths
|
||||
|
||||
#### Interactive Trigger
|
||||
|
||||
When the user asks questions such as:
|
||||
|
||||
- what should I do today
|
||||
- how should I arrange this week
|
||||
- based on my recent work, what should I focus on next
|
||||
- help me schedule upcoming work
|
||||
|
||||
The master agent should route to `schedule_planner`.
|
||||
|
||||
The expected response shape:
|
||||
|
||||
1. current conclusion
|
||||
2. today / near-term schedule recommendation
|
||||
3. next actions
|
||||
|
||||
#### Daily Scheduled Trigger
|
||||
|
||||
A daily scheduled job invokes the schedule planner flow automatically.
|
||||
|
||||
The daily run should:
|
||||
|
||||
1. collect relevant context from conversation history, tasks, and forum data
|
||||
2. run `schedule_analysis`
|
||||
3. run `schedule_planning`
|
||||
4. convert only actionable, non-duplicate recommendations into todo items
|
||||
|
||||
The daily run should not dump raw analysis into todos. Only concise, action-worthy, user-meaningful recommendations become todos.
|
||||
|
||||
## Data Flow
|
||||
|
||||
### Inputs
|
||||
|
||||
The schedule planning system should read from three sources:
|
||||
|
||||
1. **Conversation history**
|
||||
- recent user intent
|
||||
- commitments implied in prior discussion
|
||||
- stated priorities, urgency, and unresolved threads
|
||||
|
||||
2. **Task board**
|
||||
- open items
|
||||
- current statuses
|
||||
- stalled work
|
||||
- high-priority or overdue work
|
||||
|
||||
3. **Forum information**
|
||||
- new items requiring attention
|
||||
- external pressure or discussion signals
|
||||
- updates that may change priority
|
||||
|
||||
### Internal Processing
|
||||
|
||||
The main flow should be:
|
||||
|
||||
- Master decides scheduling intent
|
||||
- `schedule_planner` receives context
|
||||
- `schedule_analysis` identifies priority structure
|
||||
- `schedule_planning` produces human-usable output
|
||||
- scheduled mode additionally writes selected suggestions into todos
|
||||
|
||||
### Outputs
|
||||
|
||||
#### Interactive Output
|
||||
|
||||
The default answer structure should be:
|
||||
|
||||
- conclusion first
|
||||
- suggested schedule second
|
||||
- next actions last
|
||||
|
||||
#### Scheduled Output
|
||||
|
||||
The scheduled run should create todo entries with:
|
||||
|
||||
- concise action phrasing
|
||||
- enough context to be actionable
|
||||
- source attribution where useful (conversation/task/forum)
|
||||
- duplicate avoidance
|
||||
|
||||
## Migration Strategy
|
||||
|
||||
This redesign uses a two-phase migration to avoid breaking stored state and UI rendering.
|
||||
|
||||
### Phase 1: Compatibility Window
|
||||
|
||||
- accept legacy `planner` values from stored traces, mock payloads, and historical records
|
||||
- normalize legacy `planner` to `schedule_planner` at read boundaries where practical
|
||||
- accept legacy `planner_scope` and `planner_steps` as read-only legacy values and normalize them to `schedule_analysis` and `schedule_planning`
|
||||
- write only the new ids going forward:
|
||||
- `schedule_planner`
|
||||
- `schedule_analysis`
|
||||
- `schedule_planning`
|
||||
|
||||
### Phase 2: Legacy Removal
|
||||
|
||||
After the migration is complete and all active UI payloads, mock data, and tests are updated:
|
||||
|
||||
- remove legacy id acceptance from orchestration and frontend display logic
|
||||
- remove legacy mock fixtures
|
||||
- keep migration code out of prompts and core scheduling behavior
|
||||
|
||||
### Migration Scope
|
||||
|
||||
The migration must cover:
|
||||
|
||||
- backend enums and routing
|
||||
- frontend agent ids and telemetry labels
|
||||
- stored trace rendering paths
|
||||
- mock data used by agent dashboards and chat orchestration views
|
||||
- tests that still refer to `planner`, `planner_scope`, or `planner_steps`
|
||||
|
||||
## Input Contracts
|
||||
|
||||
The schedule planning system reads from three sources with explicit limits.
|
||||
|
||||
### Conversation History Contract
|
||||
|
||||
- use recent conversation history from the current user context
|
||||
- default retrieval window: last 7 days of relevant conversation turns, capped at the latest 50 turns
|
||||
- prefer turns that include commitments, priorities, deadlines, blockers, or future-oriented intent
|
||||
- if conversation history is unavailable, continue with degraded confidence
|
||||
|
||||
### Task Board Contract
|
||||
|
||||
- include open, in-progress, blocked, overdue, and high-priority tasks
|
||||
- exclude completed and archived items by default
|
||||
- include enough task metadata to reason about urgency and dependency:
|
||||
- title
|
||||
- status
|
||||
- priority
|
||||
- due date if present
|
||||
- last updated time if present
|
||||
- if task data is unavailable, continue with degraded confidence
|
||||
|
||||
### Forum Information Contract
|
||||
|
||||
- include recent forum items that may affect user priorities
|
||||
- default retrieval window: last 7 days of relevant forum signals
|
||||
- forum signals may include:
|
||||
- new posts requiring attention
|
||||
- replies or escalations
|
||||
- updates that change urgency or expected follow-up
|
||||
- if forum data is unavailable, continue with degraded confidence
|
||||
|
||||
## Output Contracts
|
||||
|
||||
### `schedule_analysis` Output Schema
|
||||
|
||||
The analysis stage should produce a structured summary with these fields:
|
||||
|
||||
- `top_priorities`: list of current highest-priority focus areas
|
||||
- `risks`: list of risk or pressure signals
|
||||
- `conflicts`: list of timing or dependency conflicts
|
||||
- `deferrable_items`: list of lower-priority items that can be delayed
|
||||
- `evidence`: source references grouped by `conversation`, `task_board`, or `forum`
|
||||
- `confidence`: one of `high`, `medium`, `low`
|
||||
|
||||
### `schedule_planning` Output Schema
|
||||
|
||||
The planning stage should produce a structured recommendation with these fields:
|
||||
|
||||
- `conclusion`: short decision-oriented summary
|
||||
- `today_plan`: list of suggested actions for the current day or immediate next window
|
||||
- `near_term_plan`: list of actions for the next few days or current week
|
||||
- `next_actions`: short ordered action list
|
||||
- `todo_candidates`: only present in scheduled mode; candidate todo items derived from the recommendation
|
||||
- `confidence`: one of `high`, `medium`, `low`
|
||||
|
||||
### `todo_candidates` Schema
|
||||
|
||||
Each `todo_candidate` must use this structure:
|
||||
|
||||
- `title`: required short action text
|
||||
- `description`: required short rationale grounded in source context
|
||||
- `sources`: required list of provenance objects
|
||||
- `priority`: optional normalized priority such as `high`, `medium`, `low`
|
||||
- `target_window`: optional string such as `today` or `this_week`
|
||||
|
||||
Each provenance object in `sources` must contain:
|
||||
|
||||
- `type`: one of `conversation`, `task_board`, `forum`
|
||||
- `id`: source object id when available, otherwise a stable synthetic reference
|
||||
- `label`: short human-readable source label
|
||||
|
||||
### Evidence Structure
|
||||
|
||||
Each item in `schedule_analysis.evidence` must contain:
|
||||
|
||||
- `type`: one of `conversation`, `task_board`, `forum`
|
||||
- `id`: source object id when available, otherwise a stable synthetic reference
|
||||
- `label`: short human-readable identifier
|
||||
- `reason`: brief explanation of why the signal matters to scheduling
|
||||
|
||||
### Interactive Response Contract
|
||||
|
||||
The user-facing answer should always follow this shape:
|
||||
|
||||
1. conclusion
|
||||
2. suggested schedule
|
||||
3. next actions
|
||||
|
||||
If confidence is low, the response must say that explicitly and avoid overconfident scheduling language.
|
||||
|
||||
## Daily Scheduler Contract
|
||||
|
||||
The daily scheduled trigger must follow explicit execution semantics.
|
||||
|
||||
### Execution Model
|
||||
|
||||
- run once per user per local date
|
||||
- default execution time: 07:00 in the user's configured timezone
|
||||
- if the user has no configured timezone, skip the run and log the skip reason
|
||||
- do not automatically backfill missed runs
|
||||
- enforce idempotency by `(user_id, local_date, job_type)` so the same daily analysis is not executed more than once successfully
|
||||
|
||||
### Scheduled Mode Behavior
|
||||
|
||||
A successful scheduled run should:
|
||||
|
||||
1. gather available context from the three input sources
|
||||
2. execute `schedule_analysis`
|
||||
3. execute `schedule_planning`
|
||||
4. create todo items from selected `todo_candidates`
|
||||
5. store run telemetry and outcome metadata
|
||||
|
||||
If one or more sources are missing, continue when there is still enough evidence to produce a useful recommendation and mark confidence as reduced.
|
||||
|
||||
Signal evaluation rules:
|
||||
|
||||
- a **strong source** is a source with enough current evidence to support prioritization on its own, such as multiple open high-priority tasks or a recent forum escalation
|
||||
- a **meaningful signal** is a discrete scheduling-relevant item extracted from any source, such as an overdue task, a stated commitment in conversation history, or a forum escalation
|
||||
- the planner may still run with one strong source
|
||||
- scheduled mode may create todos only when at least two meaningful signals exist across all inputs
|
||||
|
||||
If fewer than two meaningful signals are available across all sources, the scheduler should not create todos and should log a low-context outcome.
|
||||
|
||||
Delayed execution rule:
|
||||
|
||||
- if the 07:00 run is delayed by temporary outage or worker unavailability, the system may still execute one delayed run later on the same user-local date
|
||||
- if the entire local date passes without a successful run, do not backfill on the next day
|
||||
|
||||
## Todo Creation Rules
|
||||
|
||||
Todo creation is the main scheduled side effect and must be tightly constrained.
|
||||
|
||||
### Creation Rules
|
||||
|
||||
- create at most 3 todo items per daily run
|
||||
- only create todos for actions that are concrete, near-term, and user-actionable
|
||||
- do not create todos for vague advice, reflections, or duplicated reminders
|
||||
- store source provenance when available:
|
||||
- `conversation`
|
||||
- `task_board`
|
||||
- `forum`
|
||||
|
||||
### Duplicate Detection
|
||||
|
||||
A candidate todo is considered a duplicate if there is already an open todo that matches all of the following:
|
||||
|
||||
- same normalized action text
|
||||
- same source category or same source object when available
|
||||
- created within the last 7 days
|
||||
|
||||
Normalization rules for action text:
|
||||
|
||||
- trim surrounding whitespace
|
||||
- collapse repeated internal whitespace to a single space
|
||||
- lowercase Latin characters
|
||||
- remove trailing full stop / period punctuation only
|
||||
|
||||
Source comparison rules:
|
||||
|
||||
- if a provenance object includes a stable source `id`, compare by `(type, id)`
|
||||
- if no stable source id exists, compare by `(type, normalized label)`
|
||||
- if multiple sources support one recommendation, compare against the highest-priority provenance in this order: `task_board`, `forum`, `conversation`
|
||||
|
||||
When a duplicate is detected:
|
||||
|
||||
- do not create a new todo
|
||||
- record the skip reason in scheduler telemetry
|
||||
|
||||
### Todo Fields
|
||||
|
||||
Scheduled-created todos should include at minimum these persisted fields:
|
||||
|
||||
- `title`: required
|
||||
- `description`: required
|
||||
- `source_type`: required primary provenance type
|
||||
- `source_id`: optional stable source id
|
||||
- `source_label`: required fallback human-readable provenance label
|
||||
- `created_by`: required and set to `schedule_planner`
|
||||
- `created_at`: required timestamp
|
||||
- `priority`: optional normalized priority
|
||||
- `target_window`: optional normalized scheduling window
|
||||
|
||||
## Routing Boundaries
|
||||
|
||||
The system must distinguish scheduling from adjacent planning behaviors.
|
||||
|
||||
### Route to `schedule_planner` when the user asks for:
|
||||
|
||||
- today or this week planning
|
||||
- what to focus on next
|
||||
- priority ordering across ongoing work
|
||||
- time-aware sequencing of current commitments
|
||||
|
||||
### Do not route to `schedule_planner` when the user asks for:
|
||||
|
||||
- deep implementation planning for a feature
|
||||
- code execution or task fulfillment
|
||||
- research-only retrieval
|
||||
- pure analysis without scheduling intent
|
||||
|
||||
In ambiguous cases such as "what should I do next?", prefer `schedule_planner` when the available context includes multiple active tasks, recent commitments, or forum pressure signals.
|
||||
|
||||
## Backend Changes
|
||||
|
||||
### Role and Graph Layer
|
||||
|
||||
Update the orchestration layer so the planner role is redefined as `schedule_planner` rather than `planner`.
|
||||
|
||||
Files likely involved:
|
||||
|
||||
- `backend/app/agents/state.py`
|
||||
- `backend/app/agents/graph.py`
|
||||
- `backend/app/agents/prompts.py`
|
||||
- `backend/app/routers/agent.py`
|
||||
- `backend/app/services/agent_service.py`
|
||||
|
||||
Required changes:
|
||||
|
||||
- rename role ids where appropriate
|
||||
- update graph node registration
|
||||
- update master routing rules
|
||||
- replace planner subagent mappings
|
||||
- update telemetry and sub-commander trace labels
|
||||
|
||||
### Prompt Layer
|
||||
|
||||
Replace the current planner prompt family with schedule-specific instructions.
|
||||
|
||||
Needed prompt families:
|
||||
|
||||
- `SCHEDULE_PLANNER_SYSTEM_PROMPT`
|
||||
- `SCHEDULE_ANALYSIS_PROMPT`
|
||||
- `SCHEDULE_PLANNING_PROMPT`
|
||||
|
||||
Prompt requirements:
|
||||
|
||||
- reason over conversation history, tasks, and forum state
|
||||
- prioritize urgency, importance, and dependency
|
||||
- avoid abstract productivity advice
|
||||
- produce concrete, immediate scheduling output
|
||||
- in scheduled mode, generate todo-worthy suggestions only
|
||||
|
||||
### Scheduled Execution Layer
|
||||
|
||||
Add or update the daily scheduled workflow so it can call the schedule planner flow automatically.
|
||||
|
||||
Likely touchpoints:
|
||||
|
||||
- scheduler service
|
||||
- existing daily planning jobs
|
||||
- todo creation services
|
||||
|
||||
Required behavior:
|
||||
|
||||
- fixed daily execution time
|
||||
- fetch relevant context
|
||||
- call schedule planner pipeline
|
||||
- write selected recommendations into todos
|
||||
- skip duplicate todo creation
|
||||
|
||||
## Frontend Changes
|
||||
|
||||
Frontend needs to reflect the new role system consistently.
|
||||
|
||||
Files likely involved:
|
||||
|
||||
- `frontend/src/data/agents.ts`
|
||||
- `frontend/src/pages/agents/index.vue`
|
||||
- `frontend/src/components/chat/OrchestrationPanel.vue`
|
||||
- `frontend/src/pages/chat/composables/useChatView.ts`
|
||||
- related frontend tests
|
||||
|
||||
Required updates:
|
||||
|
||||
- replace planner display labels with schedule planner labels
|
||||
- rename planner subagents to schedule analysis / schedule planning
|
||||
- update orchestration telemetry labels
|
||||
- update example mock state and tests
|
||||
- use these exact frontend ids:
|
||||
- `schedule_planner`
|
||||
- `schedule_analysis`
|
||||
- `schedule_planning`
|
||||
- use these exact default Chinese labels:
|
||||
- `日程规划师`
|
||||
- `日程分析员`
|
||||
- `日程编排员`
|
||||
- update active route visualization and commander skill labels to the new ids
|
||||
|
||||
## Naming
|
||||
|
||||
### Main Agent
|
||||
|
||||
- old: `planner`
|
||||
- new: `schedule_planner`
|
||||
- display role: `日程规划师`
|
||||
|
||||
### Subagents
|
||||
|
||||
- old: `planner_scope`
|
||||
- new: `schedule_analysis`
|
||||
- display role: `日程分析员`
|
||||
|
||||
- old: `planner_steps`
|
||||
- new: `schedule_planning`
|
||||
- display role: `日程编排员`
|
||||
|
||||
## Constraints
|
||||
|
||||
- do not keep dual role names for long-term compatibility unless a specific dependency forces it
|
||||
- do not create todos for every suggestion
|
||||
- do not turn the planner into a generic life coach
|
||||
- keep scheduling grounded in current project signals
|
||||
- preserve the existing agent architecture where possible, while fully changing planner semantics
|
||||
|
||||
## Observability
|
||||
|
||||
The redesign must emit enough telemetry to debug routing and scheduled execution.
|
||||
|
||||
Required telemetry fields:
|
||||
|
||||
- selected main route
|
||||
- selected subagent
|
||||
- available input sources
|
||||
- missing input sources
|
||||
- run mode: `interactive` or `scheduled`
|
||||
- confidence level
|
||||
- todos created count
|
||||
- todos skipped as duplicates count
|
||||
- scheduler run success / skipped / failed
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
### Backend Acceptance Criteria
|
||||
|
||||
- a scheduling-intent user query routes to `schedule_planner`
|
||||
- `schedule_analysis` and `schedule_planning` are both reachable through the orchestration layer
|
||||
- legacy planner ids are normalized during the compatibility window
|
||||
- daily scheduled runs do not execute more than once per user per local date
|
||||
- low-context daily runs do not create todos
|
||||
- duplicate todo candidates are skipped instead of recreated
|
||||
|
||||
### Frontend Acceptance Criteria
|
||||
|
||||
- the agents page displays `日程规划师` instead of the previous planner label
|
||||
- the planner subagent chips display `日程分析员` and `日程编排员`
|
||||
- orchestration mock data and route highlights use the new ids
|
||||
- tests no longer depend on `planner_scope` or `planner_steps` after migration is complete
|
||||
|
||||
### Failure and Fallback Criteria
|
||||
|
||||
- if forum data is missing, the planner still runs with degraded confidence
|
||||
- if task board data is missing, the planner still runs with degraded confidence when other strong context exists
|
||||
- if fewer than two meaningful signals are available, scheduled mode creates no todos
|
||||
- if the user has no timezone configured, the daily scheduled run is skipped and logged
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
### Backend
|
||||
|
||||
Add or update tests for:
|
||||
|
||||
- master routing to `schedule_planner`
|
||||
- schedule subagent selection behavior
|
||||
- prompt invariants for schedule-focused output
|
||||
- scheduled daily run creates todos from actionable suggestions
|
||||
- duplicate todo protection
|
||||
|
||||
### Frontend
|
||||
|
||||
Add or update tests for:
|
||||
|
||||
- renamed main role and subagent labels
|
||||
- orchestration panel route display
|
||||
- active subagent telemetry
|
||||
- mock agent graph data using `schedule_planner`, `schedule_analysis`, and `schedule_planning`
|
||||
|
||||
## Risks
|
||||
|
||||
1. **Broad rename surface**
|
||||
- `planner` is referenced across backend and frontend, so a full rename must be systematic
|
||||
|
||||
2. **Scheduled todo spam**
|
||||
- daily runs may create low-value or duplicate todos unless filtered carefully
|
||||
|
||||
3. **Prompt drift**
|
||||
- if prompts stay too abstract, the new agent will sound renamed but not actually scheduling-oriented
|
||||
|
||||
## Recommendation
|
||||
|
||||
Implement this as a real role-system redesign, not as a display-only rename. The role id, subagent ids, prompt family, routing logic, and frontend telemetry should all align on the new scheduling semantics so the system remains internally coherent.
|
||||
Reference in New Issue
Block a user