上传文件至「/」

This commit is contained in:
zwz
2026-03-20 14:47:08 +00:00
parent 371728e9b1
commit ae162aa39b
5 changed files with 858 additions and 0 deletions

228
.gitignore vendored Normal file
View File

@@ -0,0 +1,228 @@
# Dependencies
node_modules/
__pycache__/
*.pyc
*.pyo
*.pyd
.Python
env/
venv/
.venv/
pip-log.txt
pip-delete-this-directory.txt
# Build outputs
dist/
build/
*.egg-info/
*.egg
.next/
out/
# Environment variables
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
*.env
# IDE and editor files
.vscode/
.idea/
*.swp
*.swo
*~
.DS_Store
Thumbs.db
# Logs
logs/
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids/
*.pid
*.seed
*.pid.lock
# Coverage directory used by tools like istanbul
coverage/
*.lcov
# nyc test coverage
.nyc_output
# Dependency directories
jspm_packages/
# Optional npm cache directory
.npm
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
# Nuxt.js build / generate output
.nuxt
# Gatsby files
.cache/
public
# Storybook build outputs
.out
.storybook-out
# Temporary folders
tmp/
temp/
# Database files
*.db
*.sqlite
*.sqlite3
# Python specific
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.whl
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Scrapy stuff
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
.python-version
# pipenv
Pipfile.lock
# PEP 582
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# OS generated files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
# Project specific
.claude/
.ruff_cache/

121
README.md Normal file
View File

@@ -0,0 +1,121 @@
# Interactive Mindmap
基于 Next.js、FastAPI 和 SQLite 的交互式思维导图应用,支持通过腾讯云 AI Agent 对话生成思维导图。
## 项目结构
```
mindmap/
├── backend/ # FastAPI 后端
│ ├── app/
│ │ ├── main.py # 应用入口
│ │ ├── config.py # 配置
│ │ ├── database.py # 数据库
│ │ ├── models.py # 数据模型
│ │ ├── schemas.py # Pydantic schemas
│ │ └── routers/
│ │ ├── mindmaps.py # 思维导图 CRUD API
│ │ └── chat.py # AI 对话代理 (SSE)
│ ├── data/ # SQLite 数据库文件
│ ├── requirements.txt
│ └── .env.example
├── frontend/ # Next.js 前端
│ ├── app/
│ │ ├── page.tsx # 首页
│ │ └── mindmap/
│ │ ├── [id]/page.tsx # 思维导图详情页
│ │ └── chat/page.tsx # AI 对话 + 思维导图页
│ ├── components/
│ │ ├── MindmapCanvas.tsx # 思维导图画布
│ │ ├── MindmapNodeCard.tsx # 节点卡片
│ │ ├── ChatPanel.tsx # 聊天面板
│ │ └── CreateMindmapForm.tsx # 创建表单
│ ├── lib/
│ │ ├── api.ts # API 调用
│ │ └── treeToGraph.ts # 树转图布局
│ └── types/
│ └── mindmap.ts # TypeScript 类型
└── mind_prompt.md # AI Agent 系统提示词
```
## 环境配置
### 后端
1. 安装依赖:
```bash
cd backend
pip install -r requirements.txt
```
2. 配置环境变量:
```bash
# 复制示例配置
cp .env.example .env
# 编辑 .env填入腾讯云 AI Agent 的 bot_app_key
TENCENT_BOT_APP_KEY=your-key-here
```
3. 启动后端:
```bash
TENCENT_BOT_APP_KEY=your-key-here uvicorn app.main:app --reload
```
### 前端
1. 安装依赖:
```bash
cd frontend
npm install
```
2. 启动开发服务器:
```bash
npm run dev
```
## 页面说明
### 首页 `/`
输入主题创建思维导图(使用 mock 数据)。
### 思维导图详情 `/mindmap/[id]`
查看已保存的思维导图,支持节点展开/收缩。
### AI 对话生成 `/mindmap/chat?sessionId=xxx`
通过与腾讯云 AI Agent 对话生成思维导图:
- **左侧**: 思维导图画布初始为空AI 返回有效数据后自动渲染
- **右侧**: 聊天面板,支持实时 SSE 流式响应
URL 参数:
- `sessionId` (必填): 会话 ID用于标识对话会话
## 数据流
```
用户输入 → ChatPanel → POST /api/chat → 后端代理 → 腾讯云 SSE API
画布更新 ← onMindmapUpdate ← JSON 解析 ← SSE 流式响应 ←─┘
```
1. 用户在聊天面板输入消息
2. 前端发送 POST 请求到后端 `/api/chat`
3. 后端将请求代理到腾讯云 AI Agent SSE 接口
4. SSE 流式响应逐步返回到前端
5. 前端解析 SSE 事件,逐步显示 AI 回复
6. 当 AI 回复完成后,尝试从回复中提取思维导图 JSON
7. 如果提取成功,更新左侧画布
## AI Agent 配置
参见 [mind_prompt.md](./mind_prompt.md) 获取 AI Agent 的系统提示词配置。

176
help.md Normal file
View File

@@ -0,0 +1,176 @@
# 思维导图工具使用说明
## 概述
本工具用于对接腾讯云智能体平台,实现思维导图的可视化展示和交互式对话。
## 工作流程
```
腾讯云智能体平台 → 发送sessionID和思维导图JSON → 本系统存储并返回URL → 用户访问URL查看思维导图 → 点击节点触发AI对话
```
## API 接口
### 1. 创建思维导图
**请求**
```
POST /api/mindmaps
Content-Type: application/json
{
"session_id": "腾讯云对话sessionID",
"mindmap_json": {
"id": "node_0",
"label": "机器学习",
"parent_id": null,
"level": 0,
"is_leaf": false,
"children": [
{
"id": "node_1",
"label": "监督学习",
"parent_id": "node_0",
"level": 1,
"is_leaf": false,
"children": []
}
]
}
}
```
**响应**
```json
{
"id": 1,
"unique_id": "abc123xyz",
"session_id": "腾讯云对话sessionID",
"title": "机器学习",
"raw_json": "{...}",
"tree": {...},
"url": "http://localhost:3000/mindmap/abc123xyz",
"created_at": "2026-03-20T12:00:00",
"updated_at": "2026-03-20T12:00:00"
}
```
**说明**
- `session_id`: 腾讯云智能体平台的对话sessionID用于后续节点点击时的对话
- `mindmap_json`: 思维导图的JSON数据标题从根节点的`label`字段自动提取
- `url`: 返回的唯一访问链接,可直接发送给用户
### 2. 获取思维导图
**请求**
```
GET /api/mindmaps/{unique_id}
```
**响应**
与创建接口返回格式相同
### 3. 对话接口
**请求**
```
POST /api/chat
Content-Type: application/json
{
"session_id": "腾讯云对话sessionID",
"content": "帮我解释一下监督学习"
}
```
**响应**
SSE流式响应转发腾讯云智能体平台的对话结果
## 思维导图JSON格式
```json
{
"id": "node_0",
"label": "根节点标题",
"parent_id": null,
"level": 0,
"is_leaf": false,
"children": [
{
"id": "node_1",
"label": "子节点标题",
"parent_id": "node_0",
"level": 1,
"is_leaf": true,
"children": []
}
]
}
```
**字段说明**
| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | string | 节点唯一标识 |
| `label` | string | 节点显示文本 |
| `parent_id` | string \| null | 父节点ID根节点为null |
| `level` | number | 节点层级根节点为0 |
| `is_leaf` | boolean | 是否为叶子节点 |
| `children` | array | 子节点数组 |
## 前端交互
1. **查看思维导图**: 用户访问返回的URL即可查看思维导图
2. **展开/折叠节点**: 点击有子节点的节点可展开或折叠
3. **触发AI对话**: 点击任意节点,右侧聊天面板会自动显示并发送"帮我解释一下{节点内容}"到腾讯云智能体平台
4. **继续对话**: 用户可在聊天面板中继续与AI对话
## 环境变量配置
后端 `.env` 文件:
```env
# 腾讯云智能体平台 AppKey
# 获取方式:应用管理 → 找到运行中的应用 → 点击"调用" → 复制AppKey
BOT_APP_KEY=your-app-key-here
# 前端基础URL用于生成思维导图链接
FRONTEND_BASE_URL=http://localhost:3000
```
前端 `.env.local` 文件:
```env
# 后端API地址
NEXT_PUBLIC_API_BASE_URL=http://127.0.0.1:8000
```
## 启动方式
### 后端
```bash
cd backend
pip install -r requirements.txt
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
```
### 前端
```bash
cd frontend
npm install
npm run dev
```
## 腾讯云智能体平台配置
在腾讯云智能体平台的系统提示词中指导AI返回符合上述格式的思维导图JSON。参考 `mind_prompt.md` 文件中的示例提示词。

178
mind_prompt.md Normal file
View File

@@ -0,0 +1,178 @@
# 思维导图 AI Agent 系统提示词
将以下内容配置为腾讯云 AI Agent 的系统提示词System Prompt
---
你是一个思维导图生成助手。当用户提出一个主题时,你需要生成一个结构化的思维导图 JSON 数据。
## 输出格式
你必须严格按照以下 JSON Schema 输出思维导图数据,不要包含任何额外的解释文字,只返回 JSON
```json
{
"id": "node_0",
"label": "根节点标题",
"parent_id": null,
"level": 0,
"is_leaf": false,
"children": [
{
"id": "node_1",
"label": "子节点标题",
"parent_id": "node_0",
"level": 1,
"is_leaf": false,
"children": [
{
"id": "node_4",
"label": "叶子节点",
"parent_id": "node_1",
"level": 2,
"is_leaf": true,
"children": []
}
]
}
]
}
```
## 字段说明
| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | string | 节点唯一标识,格式为 `node_N`N 从 0 开始递增) |
| `label` | string | 节点显示文本 |
| `parent_id` | string \| null | 父节点 ID根节点为 null |
| `level` | number | 节点层级,根节点为 0 |
| `is_leaf` | boolean | 是否为叶子节点(无子节点时为 true |
| `children` | array | 子节点数组,叶子节点为空数组 `[]` |
## 规则
1. 根节点的 `label` 应为用户提出的主题
2. 建议生成 3-5 个一级子节点
3. 每个一级子节点下建议生成 2-4 个二级子节点
4. 最多不超过 3 层level 0, 1, 2
5. **必须** 将整个 JSON 放在 ` ```json ``` ` 代码块内返回
6. 除了 JSON 代码块外,不要输出任何其他文字
## 示例
用户输入:`机器学习`
你应该返回:
```json
{
"id": "node_0",
"label": "机器学习",
"parent_id": null,
"level": 0,
"is_leaf": false,
"children": [
{
"id": "node_1",
"label": "监督学习",
"parent_id": "node_0",
"level": 1,
"is_leaf": false,
"children": [
{
"id": "node_5",
"label": "线性回归",
"parent_id": "node_1",
"level": 2,
"is_leaf": true,
"children": []
},
{
"id": "node_6",
"label": "决策树",
"parent_id": "node_1",
"level": 2,
"is_leaf": true,
"children": []
}
]
},
{
"id": "node_2",
"label": "无监督学习",
"parent_id": "node_0",
"level": 1,
"is_leaf": false,
"children": [
{
"id": "node_7",
"label": "聚类分析",
"parent_id": "node_2",
"level": 2,
"is_leaf": true,
"children": []
},
{
"id": "node_8",
"label": "降维",
"parent_id": "node_2",
"level": 2,
"is_leaf": true,
"children": []
}
]
},
{
"id": "node_3",
"label": "强化学习",
"parent_id": "node_0",
"level": 1,
"is_leaf": false,
"children": [
{
"id": "node_9",
"label": "Q-Learning",
"parent_id": "node_3",
"level": 2,
"is_leaf": true,
"children": []
},
{
"id": "node_10",
"label": "策略梯度",
"parent_id": "node_3",
"level": 2,
"is_leaf": true,
"children": []
}
]
},
{
"id": "node_4",
"label": "深度学习",
"parent_id": "node_0",
"level": 1,
"is_leaf": false,
"children": [
{
"id": "node_11",
"label": "卷积神经网络",
"parent_id": "node_4",
"level": 2,
"is_leaf": true,
"children": []
},
{
"id": "node_12",
"label": "循环神经网络",
"parent_id": "node_4",
"level": 2,
"is_leaf": true,
"children": []
}
]
}
]
}
```

155
test_api.py Normal file
View File

@@ -0,0 +1,155 @@
import requests
BASE_URL = "http://127.0.0.1:8000"
def test_create_mindmap():
payload = {
"session_id": "test-session-123456",
"mindmap_json": {
"id": "node_0",
"label": "Python编程",
"parent_id": None,
"level": 0,
"is_leaf": False,
"children": [
{
"id": "node_1",
"label": "基础语法",
"parent_id": "node_0",
"level": 1,
"is_leaf": False,
"children": [
{
"id": "node_5",
"label": "变量与数据类型",
"parent_id": "node_1",
"level": 2,
"is_leaf": True,
"children": [],
},
{
"id": "node_6",
"label": "控制流程",
"parent_id": "node_1",
"level": 2,
"is_leaf": True,
"children": [],
},
{
"id": "node_7",
"label": "函数定义",
"parent_id": "node_1",
"level": 2,
"is_leaf": True,
"children": [],
},
],
},
{
"id": "node_2",
"label": "面向对象",
"parent_id": "node_0",
"level": 1,
"is_leaf": False,
"children": [
{
"id": "node_8",
"label": "类与对象",
"parent_id": "node_2",
"level": 2,
"is_leaf": True,
"children": [],
},
{
"id": "node_9",
"label": "继承与多态",
"parent_id": "node_2",
"level": 2,
"is_leaf": True,
"children": [],
},
],
},
{
"id": "node_3",
"label": "常用库",
"parent_id": "node_0",
"level": 1,
"is_leaf": False,
"children": [
{
"id": "node_10",
"label": "NumPy",
"parent_id": "node_3",
"level": 2,
"is_leaf": True,
"children": [],
},
{
"id": "node_11",
"label": "Pandas",
"parent_id": "node_3",
"level": 2,
"is_leaf": True,
"children": [],
},
{
"id": "node_12",
"label": "Requests",
"parent_id": "node_3",
"level": 2,
"is_leaf": True,
"children": [],
},
],
},
{
"id": "node_4",
"label": "应用场景",
"parent_id": "node_0",
"level": 1,
"is_leaf": False,
"children": [
{
"id": "node_13",
"label": "Web开发",
"parent_id": "node_4",
"level": 2,
"is_leaf": True,
"children": [],
},
{
"id": "node_14",
"label": "数据分析",
"parent_id": "node_4",
"level": 2,
"is_leaf": True,
"children": [],
},
],
},
],
},
}
response = requests.post(f"{BASE_URL}/api/mindmaps", json=payload)
print("=== 创建思维导图 ===")
print(f"状态码: {response.status_code}")
result = response.json()
print(f"访问链接: {result['url']}")
print(f"标题: {result['title']}")
print(f"unique_id: {result['unique_id']}")
return result
def test_get_mindmap(unique_id):
response = requests.get(f"{BASE_URL}/api/mindmaps/{unique_id}")
print("\n=== 获取思维导图 ===")
print(f"状态码: {response.status_code}")
print(f"标题: {response.json()['title']}")
if __name__ == "__main__":
result = test_create_mindmap()
test_get_mindmap(result["unique_id"])