|
|
@@ -0,0 +1,284 @@
|
|
|
+# 工具表(Resource)与知识库对接文档
|
|
|
+
|
|
|
+## 文档维护规范
|
|
|
+
|
|
|
+0. **先改文档,再动代码** - 新功能或重大修改需先完成文档更新、并完成审阅后,再进行代码实现;除非改动较小、不被文档涵盖
|
|
|
+1. **文档分层,链接代码** - 重要或复杂设计可以另有详细文档;关键实现需标注代码文件路径;格式:`module/file.py:function_name`
|
|
|
+2. **简洁快照,日志分离** - 只记录最重要的、与代码准确对应的或者明确的已完成的设计的信息,避免推测、建议、决策历史、修改日志、大量代码;决策依据或修改日志若有必要,可在 `knowhub/docs/decisions.md` 另行记录
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 一、核心概念
|
|
|
+
|
|
|
+知识库(KnowHub)中的工具表存储在 **Resource** 模块里,与 **Knowledge**(知识条目)通过双向索引关联。
|
|
|
+
|
|
|
+| 模块 | 存储后端 | 主键格式 |
|
|
|
+|------|----------|----------|
|
|
|
+| Resource(工具表) | SQLite | `tools/{category}/{slug}` |
|
|
|
+| Knowledge(知识) | Milvus(向量库) | `knowledge-{日期}-{随机}` |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 二、Resource 数据结构
|
|
|
+
|
|
|
+### 工具表字段
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "id": "tools/plugin/ip_adapter",
|
|
|
+ "title": "IP-Adapter",
|
|
|
+ "body": "",
|
|
|
+ "content_type": "text",
|
|
|
+ "metadata": {
|
|
|
+ "category": "plugin",
|
|
|
+ "tool_slug": "ip_adapter",
|
|
|
+ "status": "未接入",
|
|
|
+ "version": "v1.0",
|
|
|
+ "description": "22M参数的轻量适配器,通过CLIP ViT-H图像编码器实现图像提示",
|
|
|
+ "usage": "scale=1.0用于纯图像提示,scale=0.5用于多模态(图像+文本)",
|
|
|
+ "scenarios": ["人物一致性控制", "风格迁移", "图像引导生成"],
|
|
|
+ "input": "参考图像 + 文本提示(可选)",
|
|
|
+ "output": "生成图像",
|
|
|
+ "source": "https://github.com/tencent-ailab/IP-Adapter",
|
|
|
+ "knowledge_ids": ["knowledge-20260309-215835-a699"],
|
|
|
+ "migrated_from": "knowhub_old"
|
|
|
+ },
|
|
|
+ "submitted_by": "migrate_script"
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### metadata 字段说明
|
|
|
+
|
|
|
+| 字段 | 类型 | 必填 | 说明 |
|
|
|
+|------|------|------|------|
|
|
|
+| `category` | string | ✅ | 分类:`image_gen` / `image_process` / `model` / `plugin` / `workflow` / `other` |
|
|
|
+| `tool_slug` | string | ✅ | 小写英文短名,空格换下划线,如 `controlnet`、`ip_adapter` |
|
|
|
+| `status` | string | ✅ | 接入状态:`未接入` / `已接入` / `测试中` |
|
|
|
+| `version` | string\|null | — | 版本号 |
|
|
|
+| `description` | string\|null | — | 一句话功能介绍 |
|
|
|
+| `usage` | string\|null | — | 核心用法说明 |
|
|
|
+| `scenarios` | array | — | 应用场景列表 |
|
|
|
+| `input` | string\|null | — | 输入类型描述 |
|
|
|
+| `output` | string\|null | — | 输出类型描述 |
|
|
|
+| `source` | string\|null | — | 来源/文档链接 |
|
|
|
+| `knowledge_ids` | array | — | 关联的知识 ID 列表(双向索引) |
|
|
|
+
|
|
|
+### ID 命名规则
|
|
|
+
|
|
|
+```
|
|
|
+tools/{category}/{slug}
|
|
|
+
|
|
|
+示例:
|
|
|
+tools/plugin/ip_adapter
|
|
|
+tools/plugin/controlnet
|
|
|
+tools/image_gen/midjourney
|
|
|
+tools/model/sdxl
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 三、双向索引机制
|
|
|
+
|
|
|
+```
|
|
|
+Resource(工具) Knowledge(知识)
|
|
|
+┌─────────────────────────┐ ┌──────────────────────────────┐
|
|
|
+│ id: tools/plugin/ip_adapter │◄────►│ id: knowledge-20260309-xxx │
|
|
|
+│ metadata.knowledge_ids: │ │ resource_ids: │
|
|
|
+│ ["knowledge-xxx"] │ │ ["tools/plugin/ip_adapter"] │
|
|
|
+└─────────────────────────┘ │ tags: {"tool": true} │
|
|
|
+ └──────────────────────────────┘
|
|
|
+```
|
|
|
+
|
|
|
+- **Resource → Knowledge**:`metadata.knowledge_ids` 存储关联知识的 ID 列表
|
|
|
+- **Knowledge → Resource**:`resource_ids` 存储关联工具的 ID 列表,同时打 `tags.tool = true` 标记
|
|
|
+
|
|
|
+### 重要:双向索引是手动维护的
|
|
|
+
|
|
|
+**目前没有任何自动同步机制**,两侧的索引相互独立存储,需要调用方自己负责保持一致。
|
|
|
+
|
|
|
+两侧的写入时机:
|
|
|
+
|
|
|
+| 方向 | 存在哪 | 写入时机 |
|
|
|
+|------|--------|----------|
|
|
|
+| Resource → Knowledge | SQLite `resources.metadata.knowledge_ids` | 创建/更新 Resource 时手动 PATCH |
|
|
|
+| Knowledge → Resource | Milvus `resource_ids` 字段 | Knowledge 创建时传入,**创建后无法通过 API 修改** |
|
|
|
+
|
|
|
+> Knowledge 的 `resource_ids` 字段目前**不在 PATCH 接口的支持范围内**,一旦 Knowledge 创建,只能通过删除重建来更改其关联的工具。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 四、API 接口
|
|
|
+
|
|
|
+服务地址由环境变量 `KNOWHUB_API` 指定(如 `http://localhost:9999`)。
|
|
|
+
|
|
|
+### 4.1 工具表(Resource)
|
|
|
+
|
|
|
+#### 创建工具
|
|
|
+```http
|
|
|
+POST /api/resource
|
|
|
+Content-Type: application/json
|
|
|
+
|
|
|
+{
|
|
|
+ "id": "tools/plugin/controlnet",
|
|
|
+ "title": "ControlNet",
|
|
|
+ "body": "",
|
|
|
+ "content_type": "text",
|
|
|
+ "metadata": {
|
|
|
+ "category": "plugin",
|
|
|
+ "tool_slug": "controlnet",
|
|
|
+ "status": "已接入",
|
|
|
+ "description": "...",
|
|
|
+ "usage": "...",
|
|
|
+ "scenarios": [...],
|
|
|
+ "knowledge_ids": []
|
|
|
+ },
|
|
|
+ "submitted_by": "your_name"
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+#### 更新工具(局部更新,推荐)
|
|
|
+```http
|
|
|
+PATCH /api/resource/tools/plugin/controlnet
|
|
|
+Content-Type: application/json
|
|
|
+
|
|
|
+{
|
|
|
+ "metadata": {
|
|
|
+ "status": "已接入",
|
|
|
+ "knowledge_ids": ["knowledge-xxx", "knowledge-yyy"]
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+> ⚠️ PATCH metadata 会**整体替换** metadata 字段,需带上所有已有字段。
|
|
|
+
|
|
|
+#### 获取工具详情
|
|
|
+```http
|
|
|
+GET /api/resource/tools/plugin/controlnet
|
|
|
+```
|
|
|
+
|
|
|
+返回额外的导航字段:`toc`(根节点)、`children`(子节点)、`prev`/`next`(同级导航)。
|
|
|
+
|
|
|
+#### 列出所有工具
|
|
|
+```http
|
|
|
+GET /api/resource?limit=1000
|
|
|
+```
|
|
|
+
|
|
|
+过滤出工具(客户端过滤):
|
|
|
+```javascript
|
|
|
+const tools = results.filter(r => r.id.startsWith("tools/"));
|
|
|
+```
|
|
|
+
|
|
|
+#### 删除工具
|
|
|
+```http
|
|
|
+DELETE /api/resource/tools/plugin/controlnet
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 4.2 知识(Knowledge)
|
|
|
+
|
|
|
+#### 搜索工具相关知识(语义搜索)
|
|
|
+```http
|
|
|
+GET /api/knowledge/search?q=IP-Adapter人物一致性&top_k=5&min_score=3
|
|
|
+```
|
|
|
+
|
|
|
+#### 列出所有工具相关知识
|
|
|
+```http
|
|
|
+GET /api/knowledge?tags=tool&status=approved,checked&page_size=200
|
|
|
+```
|
|
|
+
|
|
|
+#### 获取单条知识
|
|
|
+```http
|
|
|
+GET /api/knowledge/knowledge-20260309-215835-a699
|
|
|
+```
|
|
|
+
|
|
|
+#### 批量删除知识
|
|
|
+```http
|
|
|
+POST /api/knowledge/batch_delete
|
|
|
+Content-Type: application/json
|
|
|
+
|
|
|
+["knowledge-xxx", "knowledge-yyy"]
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 五、典型操作示例(Python)
|
|
|
+
|
|
|
+### 新增一个工具并关联知识
|
|
|
+
|
|
|
+```python
|
|
|
+import httpx
|
|
|
+
|
|
|
+KNOWHUB_API = "http://your-server:9999"
|
|
|
+
|
|
|
+# 1. 创建工具
|
|
|
+tool = {
|
|
|
+ "id": "tools/plugin/controlnet",
|
|
|
+ "title": "ControlNet",
|
|
|
+ "body": "",
|
|
|
+ "content_type": "text",
|
|
|
+ "metadata": {
|
|
|
+ "category": "plugin",
|
|
|
+ "tool_slug": "controlnet",
|
|
|
+ "status": "已接入",
|
|
|
+ "version": "v1.1",
|
|
|
+ "description": "基于条件图像控制SD生成的插件",
|
|
|
+ "usage": "提供边缘图/骨骼图/深度图等条件,精确控制生成结果",
|
|
|
+ "scenarios": ["姿势控制", "边缘控制", "深度控制"],
|
|
|
+ "input": "条件图像(canny/pose/depth等)+ 文本提示",
|
|
|
+ "output": "生成图像",
|
|
|
+ "source": "https://github.com/lllyasviel/ControlNet",
|
|
|
+ "knowledge_ids": []
|
|
|
+ },
|
|
|
+ "submitted_by": "your_name"
|
|
|
+}
|
|
|
+
|
|
|
+resp = httpx.post(f"{KNOWHUB_API}/api/resource", json=tool)
|
|
|
+print(resp.json()) # {"status": "ok", "id": "tools/plugin/controlnet"}
|
|
|
+
|
|
|
+# 2. 回填知识关联(PATCH 更新 knowledge_ids)
|
|
|
+patch = {
|
|
|
+ "metadata": {
|
|
|
+ **tool["metadata"], # 保留所有已有字段
|
|
|
+ "knowledge_ids": ["knowledge-20260309-215835-a699"]
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+resp = httpx.patch(f"{KNOWHUB_API}/api/resource/tools/plugin/controlnet", json=patch)
|
|
|
+print(resp.json()) # {"status": "ok"}
|
|
|
+```
|
|
|
+
|
|
|
+### 更新工具接入状态
|
|
|
+
|
|
|
+```python
|
|
|
+# 先获取当前 metadata,再更新
|
|
|
+resp = httpx.get(f"{KNOWHUB_API}/api/resource/tools/plugin/controlnet")
|
|
|
+tool = resp.json()
|
|
|
+meta = tool["metadata"]
|
|
|
+
|
|
|
+meta["status"] = "已接入"
|
|
|
+
|
|
|
+httpx.patch(
|
|
|
+ f"{KNOWHUB_API}/api/resource/tools/plugin/controlnet",
|
|
|
+ json={"metadata": meta}
|
|
|
+)
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 六、前端查看
|
|
|
+
|
|
|
+访问 KnowHub 管理界面,点击右上角 **🔧 工具表** 按钮:
|
|
|
+
|
|
|
+- 按 `category` Tab 切换分类
|
|
|
+- 左侧列表点击工具查看详情
|
|
|
+- 详情页显示:基础概览 / 使用指南 / 技术规格 / 消息信源 / 关联知识(可跳转)
|
|
|
+- 知识卡片底部有工具 Tag,点击可跳回工具表对应条目
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 七、注意事项
|
|
|
+
|
|
|
+1. **PATCH metadata 是整体替换**:更新前先 GET 拿到当前值,合并后再 PATCH,避免覆盖已有字段(尤其是 `knowledge_ids`)。
|
|
|
+2. **Resource ID 含斜杠**:URL 调用时需注意路径编码(框架已支持 `{resource_id:path}`,直接拼接即可,无需手动 encode)。
|
|
|
+3. **双向索引需手动维护**:创建/删除工具时,需同步更新关联 Knowledge 的 `resource_ids` 字段(PATCH `/api/knowledge/{id}`)。
|
|
|
+4. **工具筛选靠客户端**:`GET /api/resource` 返回所有 resource,需在客户端过滤 `id.startsWith("tools/")` 得到工具列表。
|